Merge pull request #12752 from hamishknight/dictionary-subscript-addressor

[stdlib] Use addressor for Dictionary's subscript(_:default:)
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 25f2daf..d837a3d 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -119,6 +119,7 @@
     single-source/StrComplexWalk
     single-source/StrToInt
     single-source/StringBuilder
+    single-source/StringComparison
     single-source/StringEdits
     single-source/StringEnum
     single-source/StringInterpolation
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/main.swift b/benchmark/utils/main.swift
index 3cf652c..13a6708 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -107,6 +107,7 @@
 import StrComplexWalk
 import StrToInt
 import StringBuilder
+import StringComparison
 import StringEdits
 import StringEnum
 import StringInterpolation
@@ -227,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..c55badb 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -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,23 @@
   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" AND SWIFTLIB_TARGET_LIBRARY)
+    if("${libkind}" STREQUAL "SHARED")
+      # 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_${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 +870,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}
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/ABIStabilityManifesto.md b/docs/ABIStabilityManifesto.md
index 6985aa4..243ccea 100644
--- a/docs/ABIStabilityManifesto.md
+++ b/docs/ABIStabilityManifesto.md
@@ -266,7 +266,7 @@
 
 ### Protocol and Existential Metadata
 
-#####<a name="witness-tables"></a>Protocol Witness Tables
+##### <a name="witness-tables"></a>Protocol Witness Tables
 
 The protocol witness table is a function table of a type's conformance to the protocol's interfaces. If the protocol also has an associated type requirement, then the witness table will store the metadata for the associated type. Protocol witness tables are used with [existential containers](#existential-containers) where the run time type is not known.
 
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index e037a74..d448702 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -196,11 +196,11 @@
 
 1. Create a separate PR for each repository that needs to be changed. Each should reference the main Swift PR and create a reference to all of the others from the main PR.
 
-2. Gate all commits on @swift-ci smoke test and merge. As stated above, it is important that *all* checkins perform PR testing since if breakage enters the tree PR testing becomes less effective. If you have done local testing (using build-toolchain) and have made appropriate changes to the other repositories then perform a smoke test and merge should be sufficient for correctness. This is not meant to check for correctness in your commits, but rather to be sure that no one landed changes in other repositories or in swift that cause your PR to no longer be correct. If you were unable to make workarounds to th eother repositories, this smoke test will break *after* Swift has built. Check the log to make sure that it is the expected failure for that platform/repository that coincides with the failure your PR is supposed to fix.
+2. Gate all commits on @swift-ci smoke test and merge. As stated above, it is important that *all* checkins perform PR testing since if breakage enters the tree PR testing becomes less effective. If you have done local testing (using build-toolchain) and have made appropriate changes to the other repositories then perform a smoke test and merge should be sufficient for correctness. This is not meant to check for correctness in your commits, but rather to be sure that no one landed changes in other repositories or in swift that cause your PR to no longer be correct. If you were unable to make workarounds to the other repositories, this smoke test will break *after* Swift has built. Check the log to make sure that it is the expected failure for that platform/repository that coincides with the failure your PR is supposed to fix.
 
 3. Merge all of the pull requests simultaneously.
 
-4. Watch the public incremental build on ci.swift.org to make sure that you did not make any mistakes. It should complete within 30-40 minutes depending on what else was being committed in the mean time.
+4. Watch the public incremental build on [ci.swift.org](https://ci.swift.org/) to make sure that you did not make any mistakes. It should complete within 30-40 minutes depending on what else was being committed in the mean time.
 
 
 ## ci.swift.org bots
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/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index 0ee1eb5..e611b58 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -751,10 +751,11 @@
   /// \param substitutions The set of substitutions required to produce the
   /// specialized conformance from the generic conformance. This list is
   /// copied so passing a temporary is permitted.
-  SpecializedProtocolConformance *
+  ProtocolConformance *
   getSpecializedConformance(Type type,
                             ProtocolConformance *generic,
-                            SubstitutionList substitutions);
+                            SubstitutionList substitutions,
+                            bool alreadyCheckedCollapsed = false);
 
   /// \brief Produce a specialized conformance, which takes a generic
   /// conformance and substitutions written in terms of the generic
@@ -768,7 +769,7 @@
   /// specialized conformance from the generic conformance. The keys must
   /// be generic parameters, not archetypes, so for example passing in
   /// TypeBase::getContextSubstitutionMap() is OK.
-  SpecializedProtocolConformance *
+  ProtocolConformance *
   getSpecializedConformance(Type type,
                             ProtocolConformance *generic,
                             const SubstitutionMap &substitutions);
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 26e8b05..c5f5c5e 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -288,8 +288,6 @@
           OnProtocol | NotSerialized | LongAttribute | RejectByParser,
          /*Not serialized */ 70)
 
-// 70 is available; it was not a serialized attribute.
-
 // HACK: Attribute needed to preserve source compatibility by downgrading errors
 // due to an SDK change in Dispatch
 SIMPLE_DECL_ATTR(_downgrade_exhaustivity_check, DowngradeExhaustivityCheck,
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c27a0c1..3fcf20f 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -784,6 +784,9 @@
   LLVM_ATTRIBUTE_DEPRECATED(
       void dump() const LLVM_ATTRIBUTE_USED,
       "only for use within the debugger");
+  LLVM_ATTRIBUTE_DEPRECATED(
+      void dump(const char *filename) const LLVM_ATTRIBUTE_USED,
+      "only for use within the debugger");
   void dump(raw_ostream &OS, unsigned Indent = 0) const;
 
   /// \brief Pretty-print the given declaration.
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index ede6e16..3740f2f 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -610,10 +610,15 @@
   mutable llvm::PointerIntPair<Decl *, 2, 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;
 
+  /// 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.
+  bool lazyMemberLoadingInProgress = false;
+
   template<class A, class B, class C>
   friend struct ::llvm::cast_convert_val;
 
@@ -634,6 +639,11 @@
   /// 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);
@@ -643,6 +653,14 @@
     return FirstDeclAndLazyMembers.getInt();
   }
 
+  bool isLoadingLazyMembers() {
+    return lazyMemberLoadingInProgress;
+  }
+
+  void setLoadingLazyMembers(bool inProgress) {
+    lazyMemberLoadingInProgress = inProgress;
+  }
+
   /// Setup the loader for lazily-loaded members.
   void setMemberLoader(LazyMemberLoader *loader, uint64_t contextData);
 
diff --git a/include/swift/AST/DeclNameLoc.h b/include/swift/AST/DeclNameLoc.h
index 067c653..216af88 100644
--- a/include/swift/AST/DeclNameLoc.h
+++ b/include/swift/AST/DeclNameLoc.h
@@ -105,6 +105,14 @@
     return getSourceLocs()[FirstArgumentLabelIndex + index];
   }
 
+  SourceLoc getStartLoc() const {
+    return getBaseNameLoc();
+  }
+
+  SourceLoc getEndLoc() const {
+    return NumArgumentLabels == 0 ? getBaseNameLoc() : getRParenLoc();
+  }
+  
   /// Retrieve the complete source range for this declaration name.
   SourceRange getSourceRange() const {
     if (NumArgumentLabels == 0) return getBaseNameLoc();
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index a073702..0f65198 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -154,6 +154,9 @@
       "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(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..d41ccf7 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",
@@ -2843,6 +2846,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", ())
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 11529ca..f750f5b 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -2339,7 +2339,10 @@
 
   SourceLoc getLoc() const { return Index->getStartLoc(); }
   SourceLoc getStartLoc() const { return Base->getStartLoc(); }
-  SourceLoc getEndLoc() const { return Index->getEndLoc(); }
+  SourceLoc getEndLoc() const {
+    auto end = Index->getEndLoc();
+    return end.isValid() ? end : Base->getEndLoc();
+  }
   
   static bool classof(const Expr *E) {
     return E->getKind() == ExprKind::Subscript;
@@ -2396,7 +2399,7 @@
                                : SubExpr->getStartLoc());
   }
   SourceLoc getEndLoc() const {
-    return NameLoc.getSourceRange().End ;
+    return NameLoc.getSourceRange().End;
   }
 
   SourceLoc getDotLoc() const { return DotLoc; }
diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h
index 9906153..5ac034e 100644
--- a/include/swift/AST/GenericEnvironment.h
+++ b/include/swift/AST/GenericEnvironment.h
@@ -155,12 +155,6 @@
   /// generic parameter types by their sugared form.
   Type getSugaredType(Type type) const;
 
-  /// Build a contextual type substitution map from a type substitution function
-  /// and conformance lookup function.
-  SubstitutionMap
-  getSubstitutionMap(TypeSubstitutionFn subs,
-                     LookupConformanceFn lookupConformance) const;
-
   SubstitutionList getForwardingSubstitutions() const;
 
   void dump(raw_ostream &os) const;
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index e2189a5..cdcbeac 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -160,20 +160,6 @@
   /// array of the generic parameters for the innermost generic type.
   ArrayRef<GenericTypeParamType *> getInnermostGenericParams() const;
 
-  /// Create a text string that describes the bindings of generic parameters
-  /// that are relevant to the given set of types, e.g.,
-  /// "[with T = Bar, U = Wibble]".
-  ///
-  /// \param types The types that will be scanned for generic type parameters,
-  /// which will be used in the resulting type.
-  ///
-  /// \param substitutions The generic parameter -> generic argument
-  /// substitutions that will have been applied to these types.
-  /// These are used to produce the "parameter = argument" bindings in the test.
-  std::string
-  gatherGenericParamBindingsText(ArrayRef<Type> types,
-                                 TypeSubstitutionFn substitutions) const;
-
   /// Retrieve the requirements.
   ArrayRef<Requirement> getRequirements() const {
     return const_cast<GenericSignature *>(this)->getRequirementsBuffer();
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/Module.h b/include/swift/AST/Module.h
index 4e99b99..4186e69 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -83,7 +83,6 @@
   class SourceFileSyntax;
   class SyntaxParsingContext;
   class SyntaxParsingContextRoot;
-  struct RawSyntaxInfo;
 }
 
 /// Discriminator for file-units.
@@ -1083,21 +1082,15 @@
   bool shouldKeepSyntaxInfo() const;
 
   syntax::SourceFileSyntax getSyntaxRoot() const;
+  void setSyntaxRoot(syntax::SourceFileSyntax &&Root);
+  bool hasSyntaxRoot() const;
 
 private:
-  friend class syntax::SyntaxParsingContext;
-  friend class syntax::SyntaxParsingContextRoot;
 
   /// If not None, the underlying vector should contain tokens of this source file.
   Optional<std::vector<Token>> AllCorrectedTokens;
 
-  /// All of the raw token syntax nodes in the underlying source.
-  std::vector<syntax::RawSyntaxInfo> AllRawTokenSyntax;
-
   SourceFileSyntaxInfo &SyntaxInfo;
-
-  void setSyntaxRoot(syntax::SourceFileSyntax &&Root);
-  bool hasSyntaxRoot() const;
 };
 
 
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index a93c5e6..7d46db8 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -112,10 +112,9 @@
 
   /// 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;
 
   /// Don't generate code using partial_apply in SIL generation.
   bool DisableSILPartialApply = 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 b9420dd..0ccd2c7 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -123,7 +123,7 @@
   };
 
 private:
-  unsigned Bits : BitWidth;
+  unsigned Bits;
 
 public:
   RecursiveTypeProperties() : Bits(0) {}
@@ -289,9 +289,10 @@
 
     /// Extra information which affects how the function is called, like
     /// regparm and the calling convention.
-    unsigned ExtInfo : 16;
+    enum { NumExtInfoBits = 7 };
+    unsigned ExtInfo : NumExtInfoBits;
   };
-  enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 16 };
+  enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 7 };
   static_assert(NumAnyFunctionTypeBits <= 32, "fits in an unsigned");
 
   struct ArchetypeTypeBitfields {
@@ -316,12 +317,13 @@
 
   struct SILFunctionTypeBitfields {
     unsigned : NumTypeBaseBits;
-    unsigned ExtInfo : 16;
+    enum { NumExtInfoBits = 6 };
+    unsigned ExtInfo : NumExtInfoBits;
     unsigned CalleeConvention : 3;
     unsigned HasErrorResult : 1;
     unsigned CoroutineKind : 2;
   };
-  enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16 + 6 };
+  enum { NumSILFunctionTypeBits = NumTypeBaseBits + 12 };
   static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
 
   struct AnyMetatypeTypeBitfields {
@@ -376,6 +378,7 @@
 
   void setRecursiveProperties(RecursiveTypeProperties properties) {
     TypeBaseBits.Properties = properties.getBits();
+    assert(TypeBaseBits.Properties == properties.getBits() && "Bits dropped!");
   }
 
 public:
@@ -412,11 +415,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();
@@ -2391,21 +2394,23 @@
   /// \brief A class which abstracts out some details necessary for
   /// making a call.
   class ExtInfo {
-    // Feel free to rearrange or add bits, but if you go over 15,
-    // you'll need to adjust both the Bits field below and
-    // BaseType::AnyFunctionTypeBits.
-
+    // 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 : uint16_t { RepresentationMask     = 0x00F };
-    enum : uint16_t { AutoClosureMask        = 0x010 };
-    enum : uint16_t { NoEscapeMask           = 0x020 };
-    enum : uint16_t { ThrowsMask             = 0x040 };
+    enum : unsigned {
+      RepresentationMask     = 0xF << 0,
+      AutoClosureMask        = 1 << 4,
+      NoEscapeMask           = 1 << 5,
+      ThrowsMask             = 1 << 6,
+      NumMaskBits            = 7
+    };
 
-    uint16_t Bits;
+    unsigned Bits; // Naturally sized for speed.
 
-    ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
+    ExtInfo(unsigned Bits) : Bits(Bits) {}
 
     friend class AnyFunctionType;
     
@@ -2503,7 +2508,7 @@
         return ExtInfo(Bits & ~ThrowsMask);
     }
 
-    uint16_t getFuncAttrKey() const {
+    unsigned getFuncAttrKey() const {
       return Bits;
     }
     
@@ -2537,6 +2542,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:
@@ -3246,20 +3256,22 @@
   /// \brief A class which abstracts out some details necessary for
   /// making a call.
   class ExtInfo {
-    // Feel free to rearrange or add bits, but if you go over 15,
-    // you'll need to adjust both the Bits field below and
-    // TypeBase::AnyFunctionTypeBits.
+    // 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 : uint16_t { RepresentationMask = 0x00F };
-    enum : uint16_t { PseudogenericMask  = 0x010 };
-    enum : uint16_t { NoEscapeMask       = 0x020 };
+    enum : unsigned {
+      RepresentationMask = 0xF << 0,
+      PseudogenericMask  = 1 << 4,
+      NoEscapeMask       = 1 << 5,
+      NumMaskBits        = 6
+    };
 
-    uint16_t Bits;
+    unsigned Bits; // Naturally sized for speed.
 
-    ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
+    ExtInfo(unsigned Bits) : Bits(Bits) {}
 
     friend class SILFunctionType;
     
@@ -3360,7 +3372,7 @@
         return ExtInfo(Bits & ~NoEscapeMask);
     }
 
-    uint16_t getFuncAttrKey() const {
+    unsigned getFuncAttrKey() const {
       return Bits;
     }
 
@@ -3682,6 +3694,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,
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/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 26ed990..cec53cd 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -359,7 +359,7 @@
   void createSILModule();
   void setPrimarySourceFile(SourceFile *SF);
 
-  bool setupForFileAt(unsigned i);
+  bool setUpForFileAt(unsigned i);
 
 public:
   SourceManager &getSourceMgr() { return SourceMgr; }
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 29fa286..626e170 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -68,6 +68,8 @@
 
 /// Information about all the inputs to the frontend.
 class FrontendInputs {
+  friend class ArgsToFrontendInputsConverter;
+
 private:
   /// The names of input files to the frontend.
   std::vector<std::string> InputFilenames;
@@ -75,26 +77,28 @@
   /// 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;
+  /// The inputs for which output should be generated. If empty, output will
+  /// be generated for the whole module, in other words, whole-module mode.
+  /// Even if every input file is mentioned here, it is not the same as
+  /// whole-module mode.
+  std::vector<SelectedInput> PrimaryInputs;
 
 public:
   // Readers:
 
   // Input filename readers
   ArrayRef<std::string> getInputFilenames() const { return InputFilenames; }
-  bool hasInputFilenames() const { return !getInputFilenames().empty(); }
+  bool haveInputFilenames() const { return !getInputFilenames().empty(); }
   unsigned inputFilenameCount() const { return getInputFilenames().size(); }
 
-  bool hasUniqueInputFilename() const { return inputFilenameCount() == 1; }
+  bool haveUniqueInputFilename() const { return inputFilenameCount() == 1; }
   const std::string &getFilenameOfFirstInput() const {
-    assert(hasInputFilenames());
+    assert(haveInputFilenames());
     return getInputFilenames()[0];
   }
 
-  bool isReadingFromStdin() {
-    return hasUniqueInputFilename() && getFilenameOfFirstInput() == "-";
+  bool isReadingFromStdin() const {
+    return haveUniqueInputFilename() && getFilenameOfFirstInput() == "-";
   }
 
   // If we have exactly one input filename, and its extension is "bc" or "ll",
@@ -110,21 +114,64 @@
 
   // 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(PrimaryInputs.size() < 2 &&
+           "have not implemented >1 primary input yet");
   }
+
+public:
+  ArrayRef<SelectedInput> getPrimaryInputs() const { return PrimaryInputs; }
+
+  unsigned primaryInputCount() const { return getPrimaryInputs().size(); }
+
+  // Primary count readers:
+
+  bool haveUniquePrimaryInput() const { return primaryInputCount() == 1; }
+
+  bool havePrimaryInputs() const { return primaryInputCount() > 0; }
+
+  bool isWholeModule() const { return !havePrimaryInputs(); }
+
+  // Count-dependend readers:
+
+  Optional<SelectedInput> getOptionalPrimaryInput() const {
+    return havePrimaryInputs() ? Optional<SelectedInput>(getPrimaryInputs()[0])
+                               : Optional<SelectedInput>();
+  }
+
+  SelectedInput getRequiredUniquePrimaryInput() const {
+    assert(haveUniquePrimaryInput());
+    return getPrimaryInputs()[0];
+  }
+
+  Optional<SelectedInput> getOptionalUniquePrimaryInput() const {
+    return haveUniquePrimaryInput()
+               ? Optional<SelectedInput>(getPrimaryInputs()[0])
+               : Optional<SelectedInput>();
+  }
+
   bool haveAPrimaryInputFile() const {
-    return hasPrimaryInput() && getPrimaryInput()->isFilename();
+    return havePrimaryInputs() && getOptionalPrimaryInput()->isFilename();
   }
+
+  Optional<StringRef> getOptionalUniquePrimaryInputFilename() const {
+    Optional<SelectedInput> primaryInput = getOptionalUniquePrimaryInput();
+    return (primaryInput && primaryInput->isFilename())
+               ? Optional<StringRef>(getInputFilenames()[primaryInput->Index])
+               : Optional<StringRef>();
+  }
+
+  bool isPrimaryInputAFileAt(unsigned i) const {
+    assertMustNotBeMoreThanOnePrimaryInput();
+    if (Optional<SelectedInput> primaryInput = getOptionalPrimaryInput())
+      return primaryInput->isFilename() && primaryInput->Index == i;
+    return false;
+  }
+
   Optional<unsigned> primaryInputFileIndex() const {
     return haveAPrimaryInputFile()
-               ? Optional<unsigned>(getPrimaryInput()->Index)
+               ? Optional<unsigned>(getOptionalPrimaryInput()->Index)
                : None;
   }
 
@@ -135,9 +182,11 @@
     return StringRef();
   }
 
+public:
   // Multi-facet readers
   StringRef baseNameOfOutput(const llvm::opt::ArgList &Args,
                              StringRef ModuleName) const;
+
   bool shouldTreatAsSIL() const;
 
   /// Return true for error
@@ -158,8 +207,31 @@
 
   // Primary input writers
 
-  void setPrimaryInput(SelectedInput si) { PrimaryInput = si; }
-  void clearPrimaryInput() { PrimaryInput = 0; }
+private:
+  std::vector<SelectedInput> &getMutablePrimaryInputs() {
+    assertMustNotBeMoreThanOnePrimaryInput();
+    return PrimaryInputs;
+  }
+
+public:
+  void clearPrimaryInputs() { getMutablePrimaryInputs().clear(); }
+
+  void setPrimaryInputToFirstFile() {
+    clearPrimaryInputs();
+    addPrimaryInput(SelectedInput(0, SelectedInput::InputKind::Filename));
+  }
+
+  void addPrimaryInput(SelectedInput si) { PrimaryInputs.push_back(si); }
+
+  void setPrimaryInput(SelectedInput si) {
+    clearPrimaryInputs();
+    getMutablePrimaryInputs().push_back(si);
+  }
+
+  void addPrimaryInputFilename(unsigned index) {
+    addPrimaryInput(SelectedInput(index, SelectedInput::InputKind::Filename));
+  }
+
   void setPrimaryInputForInputFilename(const std::string &inputFilename) {
     setPrimaryInput(!inputFilename.empty() && inputFilename != "-"
                         ? SelectedInput(inputFilenameCount(),
@@ -174,12 +246,6 @@
     InputFilenames.clear();
     InputBuffers.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.
@@ -214,7 +280,7 @@
   }
   bool isOutputFileDirectory() const;
   bool isOutputFilePlainFile() const;
-  bool hasNamedOutputFile() const {
+  bool haveNamedOutputFile() const {
     return !OutputFilenames.empty() && !isOutputFilenameStdout();
   }
   void setOutputFileList(DiagnosticEngine &Diags,
@@ -474,7 +540,7 @@
 
   bool isCompilingExactlyOneSwiftFile() const {
     return InputKind == InputFileKind::IFK_Swift &&
-           Inputs.hasUniqueInputFilename();
+           Inputs.haveUniqueInputFilename();
   }
 
   void setModuleName(DiagnosticEngine &Diags, const llvm::opt::ArgList &Args);
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/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 2e81178..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">;
@@ -263,6 +263,9 @@
 def enable_sil_ownership : Flag<["-"], "enable-sil-ownership">,
   HelpText<"Enable the SIL Ownership Model">;
 
+def enable_guaranteed_normal_arguments : Flag<["-"], "enable-guaranteed-normal-arguments">,
+  HelpText<"If set to true, all normal parameters (except to inits/setters) will be passed at +0">;
+
 def disable_mandatory_semantic_arc_opts : Flag<["-"], "disable-mandatory-semantic-arc-opts">,
   HelpText<"Disable the mandatory semantic arc optimizer">;
 
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/Lexer.h b/include/swift/Parse/Lexer.h
index f41a627..1800744 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -28,11 +28,6 @@
 
 namespace swift {
 
-namespace syntax {
-  struct RawTokenSyntax;
-  struct RawSyntaxInfo;
-}
-
   /// Given a pointer to the starting byte of a UTF8 character, validate it and
   /// advance the lexer past it.  This returns the encoded character or ~0U if
   /// the encoding is invalid.
@@ -239,14 +234,24 @@
     return CodeCompletionPtr != nullptr;
   }
 
-  void lex(Token &Result) {
+  /// Lex a token. If \c TriviaRetentionMode is \c WithTrivia, passed pointers
+  /// to trivias are populated.
+  void lex(Token &Result, syntax::Trivia &LeadingTriviaResult,
+           syntax::Trivia &TrailingTriviaResult) {
     Result = NextToken;
-    if (Result.isNot(tok::eof))
+    LeadingTriviaResult = {LeadingTrivia};
+    TrailingTriviaResult = {TrailingTrivia};
+    if (Result.isNot(tok::eof)) {
+      LeadingTrivia.clear();
+      TrailingTrivia.clear();
       lexImpl();
+    }
   }
 
-  /// Lex a full token including leading and trailing trivia.
-  syntax::RawSyntaxInfo fullLex();
+  void lex(Token &Result) {
+    syntax::Trivia LeadingTrivia, TrailingTrivia;
+    lex(Result, LeadingTrivia, TrailingTrivia);
+  }
 
   bool isKeepingComments() const {
     return RetainComments == CommentRetentionMode::ReturnAsTokens;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 4b2f273..c627bbd 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -31,6 +31,8 @@
 #include "swift/Parse/PersistentParserState.h"
 #include "swift/Parse/Token.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"
 
@@ -55,10 +57,9 @@
   
   namespace syntax {
     class AbsolutePosition;
-    class SyntaxParsingContext;
-    struct RawSyntaxInfo;
     struct RawTokenSyntax;
     enum class SyntaxKind;
+    class TypeSyntax;
   }// end of syntax namespace
 
   /// Different contexts in which BraceItemList are parsed.
@@ -198,6 +199,14 @@
   /// \brief This is the current token being considered by the parser.
   Token Tok;
 
+  /// \brief leading trivias for \c Tok.
+  /// Always empty if !SF.shouldKeepSyntaxInfo().
+  syntax::Trivia LeadingTrivia;
+
+  /// \brief trailing trivias for \c Tok.
+  /// Always empty if !SF.shouldKeepSyntaxInfo().
+  syntax::Trivia TrailingTrivia;
+
   /// \brief The receiver to collect all consumed tokens.
   ConsumeTokenReceiver *TokReceiver;
 
@@ -411,16 +420,24 @@
     Parser &P;
     ParserPosition PP;
     DiagnosticTransaction DT;
+    /// This context immediately deconstructed with transparent accumulation
+    /// on cancelBacktrack().
+    llvm::Optional<syntax::SyntaxParsingContext> SynContext;
     bool Backtrack = true;
 
   public:
     BacktrackingScope(Parser &P)
-      : P(P), PP(P.getParserPosition()), DT(P.Diags) {}
+        : P(P), PP(P.getParserPosition()), DT(P.Diags) {
+      SynContext.emplace(P.SyntaxContext);
+      SynContext->setDiscard();
+    }
 
     ~BacktrackingScope();
 
     void cancelBacktrack() {
       Backtrack = false;
+      SynContext->setTransparent();
+      SynContext.reset();
       DT.commit();
     }
   };
@@ -576,7 +593,8 @@
 
   /// \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);
 
   swift::ScopeInfo &getScopeInfo() { return State->getScopeInfo(); }
 
@@ -915,12 +933,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);
 
@@ -931,9 +947,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);
@@ -945,11 +961,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();
@@ -1166,6 +1184,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();
@@ -1426,12 +1445,6 @@
                    unsigned BufferID,
                    unsigned Offset = 0,
                    unsigned EndOffset = 0);
-
-
-void populateTokenSyntaxMap(const LangOptions &LangOpts,
-                            const SourceManager &SM,
-                            unsigned BufferID,
-                            std::vector<syntax::RawSyntaxInfo> &Result);
 } // end namespace swift
 
 #endif
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/HeapObject.h b/include/swift/Runtime/HeapObject.h
index d3498ff..501b845 100644
--- a/include/swift/Runtime/HeapObject.h
+++ b/include/swift/Runtime/HeapObject.h
@@ -1243,7 +1243,9 @@
 #endif /* SWIFT_OBJC_INTEROP */
 
 /// Return the name of a Swift type represented by a metadata object.
-SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
+/// func _getTypeName(_ type: Any.Type, qualified: Bool)
+///   -> (UnsafePointer<UInt8>, Int)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 TwoWordPair<const char *, uintptr_t>::Return
 swift_getTypeName(const Metadata *type, bool qualified);  
 
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 27a8a51..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));
   }
@@ -1247,6 +1247,14 @@
     llvm_unreachable("Can not emit a destructure for this type of operand.");
   }
 
+  void
+  emitShallowDestructureValueOperation(SILLocation Loc, SILValue Operand,
+                                       llvm::SmallVectorImpl<SILValue> &Result);
+
+  void emitShallowDestructureAddressOperation(
+      SILLocation Loc, SILValue Operand,
+      llvm::SmallVectorImpl<SILValue> &Result);
+
   ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
                                      SILDeclRef Member, SILType MethodTy) {
     return insert(new (getModule()) ClassMethodInst(
@@ -1274,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 *
@@ -1442,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));
   }
@@ -1912,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
@@ -1936,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/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index bc3acf9..cdda0cf 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -227,6 +227,10 @@
   bool isFunc() const {
     return kind == Kind::Func;
   }
+
+  /// True if the SILDeclRef references a setter function.
+  bool isSetter() const;
+
   /// True if the SILDeclRef references a constructor entry point.
   bool isConstructor() const {
     return kind == Kind::Allocator || kind == Kind::Initializer;
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/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/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..a57d2ff 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.
diff --git a/include/swift/Syntax/SyntaxParsingContext.h b/include/swift/Syntax/SyntaxParsingContext.h
index 9eba962..c1256d7 100644
--- a/include/swift/Syntax/SyntaxParsingContext.h
+++ b/include/swift/Syntax/SyntaxParsingContext.h
@@ -15,146 +15,184 @@
 
 #include "swift/Basic/SourceLoc.h"
 #include "swift/Syntax/Syntax.h"
+#include "swift/Syntax/TokenSyntax.h"
 
 namespace swift {
-  class SourceLoc;
-  class SourceFile;
-  class Token;
+class SourceLoc;
+class SourceFile;
+class Token;
 
 namespace syntax {
-  struct RawTokenSyntax;
-  struct RawSyntax;
-  enum class SyntaxKind;
+struct RawTokenSyntax;
+struct RawSyntax;
+enum class SyntaxKind;
 
-enum class SyntaxContextKind: uint8_t{
-  Expr,
+enum class SyntaxContextKind {
   Decl,
   Stmt,
+  Expr,
+  Type,
+  Pattern,
 };
 
-/// The handler for parser to generate libSyntax entities.
-struct RawSyntaxInfo {
-  /// Start and end location of this syntax node.
-  SourceRange SyntaxRange;
+/// Indicates what action should be performed on the destruction of
+///  SyntaxParsingContext
+enum class AccumulationMode {
+  // Coerece the result to one of ContextKind.
+  // E.g. for ContextKind::Expr, passthroug if the result is CallExpr, whereas
+  // <UnknownExpr><SomeDecl /></UnknownDecl> for non Exprs.
+  CoerceKind,
 
-  /// This location must be valid if this node is an implicit node, e.g.
-  /// an empty statement list collection.
-  /// This location indicates the implicit node should appear before the token
-  /// on the location.
-  SourceLoc BeforeLoc;
+  // Construct a result Syntax with specified SyntaxKind.
+  CreateSyntax,
 
-  /// The raw node.
-  RC<RawSyntax> RawNode;
-  RawSyntaxInfo(RC<RawSyntax> RawNode): RawNode(RawNode) {}
-  RawSyntaxInfo(SourceLoc StartLoc, RC<RawSyntax> RawNode):
-    SyntaxRange(StartLoc), RawNode(RawNode) {}
-  RawSyntaxInfo(SourceRange SyntaxRange, RC<RawSyntax> RawNode):
-    SyntaxRange(SyntaxRange), RawNode(RawNode) {}
+  // Pass through all parts to the parent context.
+  Transparent,
 
-  bool isImplicit() const { return SyntaxRange.isInvalid(); }
-  SourceLoc getStartLoc() const { return SyntaxRange.Start; }
-  SourceLoc getEndLoc() const { return SyntaxRange.End; }
+  // Discard all parts in the context.
+  Discard,
 
-  template <typename SyntaxNode>
-  SyntaxNode makeSyntax() const { return make<SyntaxNode>(RawNode); }
-
-  template <typename RawSyntaxNode>
-  RC<RawSyntaxNode> getRaw() const {
-    return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
-  }
-  void brigeWithContext(SyntaxContextKind Kind);
-  void setBeforeLoc(SourceLoc Loc) {
-    assert(isImplicit());
-    BeforeLoc = Loc;
-  }
-};
-
-enum class SyntaxParsingContextKind: uint8_t {
+  // Construct SourceFile syntax to the specified SF.
   Root,
-  Child,
+
+  // Invalid.
+  NotSet,
 };
 
-/// The base class of different kinds of Syntax context that Parser should use to
-/// create syntax nodes.
+/// RAII object which receive RawSyntax parts. On destruction, this constructs
+/// a specified syntax node from received parts and propagate it to the parent
+/// context.
+///
+/// e.g.
+///   parseExprParen() {
+///     SyntaxParsingContext LocalCtxt(SyntaxKind::ParenExpr, SyntaxContext);
+///     consumeToken(tok::l_paren) // In consumeToken(), a RawTokenSyntax is
+///                                // added to the context.
+///     parseExpr(); // On returning from parseExpr(), a Expr Syntax node is
+///                  // created and added to the context.
+///     consumeToken(tok::r_paren)
+///     // Now the context holds { '(' Expr ')' }.
+///     // From these parts, it creates ParenExpr node and add it to the parent.
+///   }
 class SyntaxParsingContext {
-protected:
-  SyntaxParsingContext(SourceFile &SF, unsigned BufferID, Token &Tok);
-  SyntaxParsingContext(SyntaxParsingContext &Another);
-public:
-  struct ContextInfo;
-  ContextInfo &ContextData;
-  const Token &Tok;
-
-  // Get the context kind.
-  virtual SyntaxParsingContextKind getKind() = 0;
-
-  // Create a syntax node of the given kind.
-  virtual void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) = 0;
-  virtual ~SyntaxParsingContext();
-  virtual void setSyntaxKind(SyntaxKind Kind) = 0;
-  virtual void setContextKind(SyntaxContextKind CKind) = 0;
-  virtual void finalize() = 0;
-
-  // Disable the building of syntax tree in the current context.
-  void disable();
-};
-
-// The start point of syntax tree parsing. This context is the root
-// of all other entity-specific contexts. This is the context Parser
-// has when the parser instance is firstly created.
-class SyntaxParsingContextRoot: public SyntaxParsingContext {
-  SourceFile &File;
-public:
-  SyntaxParsingContextRoot(SourceFile &File, unsigned BufferID, Token &Tok):
-    SyntaxParsingContext(File, BufferID, Tok), File(File) {}
-  ~SyntaxParsingContextRoot();
-  void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override {};
-  void setSyntaxKind(SyntaxKind Kind) override {};
-  void setContextKind(SyntaxContextKind CKind) override {};
-  void finalize() override {};
-  SyntaxParsingContextKind getKind() override {
-    return SyntaxParsingContextKind::Root;
-  };
-};
-
-// The base class for contexts that are created from a parent context.
-// The stack instance will set the context holder when the context
-// is firstly created and reset the context holder to the parent when
-// it's destructed.
-class SyntaxParsingContextChild: public SyntaxParsingContext {
+  // Parent context. Only the root context has nullptr.
   SyntaxParsingContext *Parent;
-  SyntaxParsingContext *&ContextHolder;
-  Optional<SyntaxContextKind> ContextKind;
-  Optional<SyntaxKind> KnownSyntax;
-  void makeNodeWhole(SyntaxKind Kind);
-  SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-                            Optional<SyntaxContextKind> Kind,
-                            Optional<SyntaxKind> KnownSyntax);
-  bool isTopOfContextStack() const { return this == ContextHolder; }
-public:
-  SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-    SyntaxContextKind Kind): SyntaxParsingContextChild(ContextHolder,
-                                                       Kind, None) {}
 
-  SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-    SyntaxKind KnownSyntax): SyntaxParsingContextChild(ContextHolder,
-                             None, KnownSyntax) {};
+  // Reference to the
+  SyntaxParsingContext *&CtxtHolder;
 
-  SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-                            bool Disable = false);
+  // Collected parts.
+  std::vector<RC<RawSyntax>> Parts;
 
-  ~SyntaxParsingContextChild();
-  void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override;
-  void finalize() override;
-  SyntaxParsingContext* getParent() { return Parent; }
-  void setSyntaxKind(SyntaxKind SKind) override;
-  void setContextKind(SyntaxContextKind CKind) override;
-  SyntaxParsingContextRoot &getRoot();
-  SyntaxParsingContextKind getKind() override {
-    return SyntaxParsingContextKind::Child;
+  // Operation on destruction.
+  AccumulationMode Mode = AccumulationMode::NotSet;
+
+  // Additional info depending on \c Mode.
+  union {
+    // For AccumulationMode::CreateSyntax; desired syntax node kind.
+    SyntaxKind SynKind;
+    // For AccumulationMode::CoerceKind; desired syntax node category.
+    SyntaxContextKind CtxtKind;
+    // For AccumulationMode::Root; the parsing source file.
+    SourceFile *SF;
   };
-};
-}
-}
-#endif // SWIFT_SYNTAX_PARSING_CONTEXT_H
 
+  // 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),
+        Enabled(Parent->isEnabled()) {
+    assert(CtxtHolder->isTopOfContextStack() &&
+           "SyntaxParsingContext cannot have multiple children");
+    CtxtHolder = this;
+  }
+
+  SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder, SyntaxContextKind Kind)
+      : SyntaxParsingContext(CtxtHolder) {
+    setCoerceKind(Kind);
+  }
+
+  SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder, SyntaxKind Kind)
+      : SyntaxParsingContext(CtxtHolder) {
+    setCreateSyntax(Kind);
+  }
+
+  ~SyntaxParsingContext();
+
+  void disable() { Enabled = false; }
+  bool isEnabled() const { return Enabled; }
+  bool isRoot() const { return !Parent; }
+  bool isTopOfContextStack() const { return this == CtxtHolder; }
+
+  SyntaxParsingContext *getRoot();
+
+  /// Add RawSyntax to the parts.
+  void addRawSyntax(RC<RawSyntax> Raw);
+
+  /// Add Token with Trivia to the parts.
+  void addToken(Token &Tok, Trivia &LeadingTrivia, Trivia &TrailingTrivia);
+
+  /// Add Syntax to the parts.
+  void addSyntax(Syntax Node);
+
+  RC<RawSyntax> popBack() {
+    auto Raw = std::move(Parts.back());
+    Parts.pop_back();
+    return Raw;
+  }
+
+  template<typename SyntaxNode>
+  llvm::Optional<SyntaxNode> popIf() {
+    if (auto Node = make<Syntax>(Parts.back()).getAs<SyntaxNode>()) {
+      Parts.pop_back();
+      return Node;
+    }
+    return None;
+  }
+
+  TokenSyntax popToken() {
+    assert(Parts.back()->Kind == SyntaxKind::Token);
+    return make<TokenSyntax>(popBack());
+  }
+
+  /// 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);
+
+  /// On destruction, construct a specified kind of RawSyntax node consuming the
+  /// collected parts, then append it to the parent context.
+  void setCreateSyntax(SyntaxKind Kind) {
+    Mode = AccumulationMode::CreateSyntax;
+    SynKind = Kind;
+  }
+
+  /// On destruction, if the parts size is 1 and it's kind of \c Kind, just
+  /// append it to the parent context. Otherwise, create Unknown{Kind} node from
+  /// the collected parts.
+  void setCoerceKind(SyntaxContextKind Kind) {
+    Mode = AccumulationMode::CoerceKind;
+    CtxtKind = Kind;
+  }
+
+  /// Move the collected parts to the tail of parent context.
+  void setTransparent() { Mode = AccumulationMode::Transparent; }
+
+  /// Discard collected parts on this context.
+  void setDiscard() { Mode = AccumulationMode::Discard; }
+
+};
+
+} // namespace syntax
+} // namespace swift
+#endif // SWIFT_SYNTAX_PARSING_CONTEXT_H
diff --git a/include/swift/Syntax/Trivia.h b/include/swift/Syntax/Trivia.h
index 75137c0..6e072c5 100644
--- a/include/swift/Syntax/Trivia.h
+++ b/include/swift/Syntax/Trivia.h
@@ -231,6 +231,11 @@
     Pieces.insert(Pieces.begin(), Piece);
   }
 
+  /// Clear pieces.
+  void clear() {
+    Pieces.clear();
+  }
+
   /// Return a reference to the first piece.
   ///
   /// Precondition: !empty()
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index cd854df..cdf0a4e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -58,6 +58,8 @@
           "# of generic signature builders successfully registered");
 STATISTIC(NumRegisteredGenericSignatureBuildersAlready,
           "# of generic signature builders already registered");
+STATISTIC(NumCollapsedSpecializedProtocolConformances,
+          "# of specialized protocol conformances collapsed");
 
 /// Define this to 1 to enable expensive assertions of the
 /// GenericSignatureBuilder.
@@ -1897,10 +1899,48 @@
   return result;
 }
 
-SpecializedProtocolConformance *
+/// If one of the ancestor conformances already has a matching type, use
+/// that instead.
+static ProtocolConformance *collapseSpecializedConformance(
+                                             Type type,
+                                             ProtocolConformance *conformance) {
+  while (true) {
+    // If the conformance matches, return it.
+    if (conformance->getType()->isEqual(type))
+      return conformance;
+
+    switch (conformance->getKind()) {
+    case ProtocolConformanceKind::Inherited:
+      conformance = cast<InheritedProtocolConformance>(conformance)
+                      ->getInheritedConformance();
+      break;
+
+    case ProtocolConformanceKind::Specialized:
+      conformance = cast<SpecializedProtocolConformance>(conformance)
+                      ->getGenericConformance();
+      break;
+
+    case ProtocolConformanceKind::Normal:
+      return nullptr;
+    }
+  }
+}
+
+ProtocolConformance *
 ASTContext::getSpecializedConformance(Type type,
                                       ProtocolConformance *generic,
-                                      SubstitutionList substitutions) {
+                                      SubstitutionList substitutions,
+                                      bool alreadyCheckedCollapsed) {
+  // If we are performing a substitution that would get us back to the
+  // a prior conformance (e.g., mapping into and then out of a conformance),
+  // return the existing conformance.
+  if (!alreadyCheckedCollapsed) {
+    if (auto existing = collapseSpecializedConformance(type, generic)) {
+      ++NumCollapsedSpecializedProtocolConformances;
+      return existing;
+    }
+  }
+
   llvm::FoldingSetNodeID id;
   SpecializedProtocolConformance::Profile(id, type, generic, substitutions);
 
@@ -1922,15 +1962,24 @@
   return result;
 }
 
-SpecializedProtocolConformance *
+ProtocolConformance *
 ASTContext::getSpecializedConformance(Type type,
                                       ProtocolConformance *generic,
                                       const SubstitutionMap &subMap) {
+  // If we are performing a substitution that would get us back to the
+  // a prior conformance (e.g., mapping into and then out of a conformance),
+  // return the existing conformance.
+  if (auto existing = collapseSpecializedConformance(type, generic)) {
+    ++NumCollapsedSpecializedProtocolConformances;
+    return existing;
+  }
+
   SmallVector<Substitution, 4> subs;
   if (auto *genericSig = generic->getGenericSignature())
     genericSig->getSubstitutions(subMap, subs);
 
-  return getSpecializedConformance(type, generic, subs);
+  return getSpecializedConformance(type, generic, subs,
+                                   /*alreadyCheckedCollapsed=*/true);
 }
 
 InheritedProtocolConformance *
@@ -3820,6 +3869,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 620b828..75f2e93 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -14,7 +14,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "swift/Basic/QuotedString.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ASTPrinter.h"
 #include "swift/AST/ASTVisitor.h"
@@ -24,12 +23,14 @@
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/AST/TypeVisitor.h"
+#include "swift/Basic/QuotedString.h"
 #include "swift/Basic/STLExtras.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/raw_ostream.h"
@@ -1177,6 +1178,16 @@
   dump(llvm::errs(), 0);
 }
 
+void Decl::dump(const char *filename) const {
+  std::error_code ec;
+  llvm::raw_fd_ostream stream(filename, ec, llvm::sys::fs::F_RW);
+  // In assert builds, we blow up. Otherwise, we just return.
+  assert(!ec && "Failed to open file for dumping?!");
+  if (ec)
+    return;
+  dump(stream, 0);
+}
+
 void Decl::dump(raw_ostream &OS, unsigned Indent) const {
   // Make sure to print type variables.
   llvm::SaveAndRestore<bool> X(getASTContext().LangOpts.DebugConstraintSolver,
@@ -3047,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());
@@ -3057,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()) {
@@ -3070,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..887e0e1 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
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..be0e87f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -5395,15 +5395,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..6865794 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.
diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp
index 70d84d7..c932f9b 100644
--- a/lib/AST/GenericEnvironment.cpp
+++ b/lib/AST/GenericEnvironment.cpp
@@ -228,46 +228,3 @@
   genericSig->getSubstitutions(subMap, result);
   return genericSig->getASTContext().AllocateCopy(result);
 }
-
-SubstitutionMap
-GenericEnvironment::
-getSubstitutionMap(TypeSubstitutionFn subs,
-                   LookupConformanceFn lookupConformance) const {
-  SubstitutionMap subMap(const_cast<GenericEnvironment *>(this));
-
-  getGenericSignature()->enumeratePairedRequirements(
-    [&](Type depTy, ArrayRef<Requirement> reqs) -> bool {
-      auto canTy = depTy->getCanonicalType();
-
-      // Map the interface type to a context type.
-      auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
-                                   MakeAbstractConformanceForGenericType());
-
-      // Compute the replacement type.
-      Type currentReplacement = contextTy.subst(subs, lookupConformance,
-                                                SubstFlags::UseErrorType);
-
-      if (auto paramTy = dyn_cast<GenericTypeParamType>(canTy))
-        subMap.addSubstitution(paramTy, currentReplacement);
-
-      // Collect the conformances.
-      for (auto req: reqs) {
-        assert(req.getKind() == RequirementKind::Conformance);
-        auto protoType = req.getSecondType()->castTo<ProtocolType>();
-        auto conformance = lookupConformance(canTy,
-                                             currentReplacement,
-                                             protoType);
-        if (conformance) {
-          assert(conformance->getConditionalRequirements().empty() &&
-                 "unhandled conditional requirements");
-
-          subMap.addConformance(canTy, *conformance);
-        }
-      }
-
-      return false;
-    });
-
-  subMap.verify();
-  return subMap;
-}
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 4279839..2c61f001 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -110,45 +110,6 @@
   return result;
 }
 
-std::string GenericSignature::gatherGenericParamBindingsText(
-    ArrayRef<Type> types, TypeSubstitutionFn substitutions) const {
-  llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams;
-  for (auto type : types) {
-    type.visit([&](Type type) {
-      if (auto gp = type->getAs<GenericTypeParamType>()) {
-        knownGenericParams.insert(
-            gp->getCanonicalType()->castTo<GenericTypeParamType>());
-      }
-    });
-  }
-
-  if (knownGenericParams.empty())
-    return "";
-
-  SmallString<128> result;
-  for (auto gp : this->getGenericParams()) {
-    auto canonGP = gp->getCanonicalType()->castTo<GenericTypeParamType>();
-    if (!knownGenericParams.count(canonGP))
-      continue;
-
-    if (result.empty())
-      result += " [with ";
-    else
-      result += ", ";
-    result += gp->getName().str();
-    result += " = ";
-
-    auto type = substitutions(canonGP);
-    if (!type)
-      return "";
-
-    result += type.getString();
-  }
-
-  result += "]";
-  return result.str().str();
-}
-
 ASTContext &GenericSignature::getASTContext(
                                 ArrayRef<swift::GenericTypeParamType *> params,
                                 ArrayRef<swift::Requirement> requirements) {
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 2465611..fc85b1f 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -609,20 +609,19 @@
   auto type = assocType->getCanonicalType();
   auto proto = getRequirement();
 
-#if false
   // Fast path for generic parameters.
   if (isa<GenericTypeParamType>(type)) {
     assert(type->isEqual(proto->getSelfInterfaceType()) &&
            "type parameter in protocol was not Self");
-    return getType();
+    return conformingType;
   }
 
   // Fast path for dependent member types on 'Self' of our associated types.
   auto memberType = cast<DependentMemberType>(type);
   if (memberType.getBase()->isEqual(proto->getProtocolSelfType()) &&
-      memberType->getAssocType()->getProtocol() == proto)
-    return getTypeWitness(memberType->getAssocType(), nullptr);
-#endif
+      memberType->getAssocType()->getProtocol() == proto &&
+      isConcrete())
+    return getConcrete()->getTypeWitness(memberType->getAssocType(), resolver);
 
   // General case: consult the substitution map.
   auto substMap =
@@ -958,10 +957,8 @@
              && "substitution mapped to different nominal?!");
 
       SubstitutionMap subMap;
-      if (getGenericSignature()) {
-        auto *genericEnv = getGenericEnvironment();
-        subMap = genericEnv->getSubstitutionMap(subs, conformances);
-      }
+      if (auto *genericSig = getGenericSignature())
+        subMap = genericSig->getSubstitutionMap(subs, conformances);
 
       return substType->getASTContext()
         .getSpecializedConformance(substType,
@@ -979,7 +976,14 @@
       = cast<InheritedProtocolConformance>(this)->getInheritedConformance();
     ProtocolConformance *newBase;
     if (inheritedConformance->getType()->isSpecialized()) {
-      newBase = inheritedConformance->subst(substType, subs, conformances);
+      // Follow the substituted type up the superclass chain until we reach
+      // the underlying class type.
+      auto targetClass =
+        inheritedConformance->getType()->getClassOrBoundGenericClass();
+      auto superclassType = substType->getSuperclassForDecl(targetClass);
+
+      // Substitute into the superclass.
+      newBase = inheritedConformance->subst(superclassType, subs, conformances);
     } else {
       newBase = inheritedConformance;
     }
@@ -1016,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/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp
index a8f1854..2e4db85 100644
--- a/lib/AST/SubstitutionMap.cpp
+++ b/lib/AST/SubstitutionMap.cpp
@@ -224,7 +224,7 @@
            substType->castTo<ArchetypeType>()->getSuperclass()) &&
           !substType->isTypeParameter() &&
           !substType->isExistentialType()) {
-        return *M->lookupConformance(substType, proto);
+        return M->lookupConformance(substType, proto);
       }
 
       return ProtocolConformanceRef(proto);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 92ba99b..f48268c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -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;
@@ -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();
 
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/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 4a973b2..241f9ce 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -3278,8 +3278,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 +3329,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/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 15728f8..a0a9b75 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;
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index af63aa1..60e41d5 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);
@@ -1530,26 +1533,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 +1610,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 +1626,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 +1726,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 +1758,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..df4a47a 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,9 @@
   FrontendOptions.cpp
   PrintingDiagnosticConsumer.cpp
   SerializedDiagnosticConsumer.cpp
-  ${AppleHostVersionDetection}
-  DEPENDS SwiftOptions
+  DEPENDS
+    SwiftOptions
+    swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftSIL
     swiftMigrator
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 1df15a9..5d7dd75 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;
@@ -83,6 +79,147 @@
   llvm_unreachable("Unhandled InputFileKind in switch.");
 }
 
+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;
+
+  llvm::StringMap<unsigned> FileIndices;
+  std::vector<StringRef> PrimaryFiles;
+
+  StringRef filelistPath() { return FilelistPathArg->getValue(); }
+
+  void addPrimary(StringRef file) { PrimaryFiles.push_back(file); }
+
+  void addInput(StringRef file) {
+    FileIndices.insert({file, Inputs.inputFilenameCount()});
+    Inputs.addInputFilename(file);
+  }
+
+  bool arePrimariesOnCommandLineAlsoAppearingInFilelist() {
+    return FilelistPathArg != nullptr;
+  }
+
+  enum class Whence {
+    PrimaryFromCommandLine,
+    SecondaryFromCommandLine,
+    SecondaryFromFileList
+  };
+
+  void addFile(StringRef file, Whence whence) {
+    switch (whence) {
+    case Whence::PrimaryFromCommandLine:
+      addPrimary(file);
+      if (!arePrimariesOnCommandLineAlsoAppearingInFilelist())
+        addInput(file);
+      break;
+    case Whence::SecondaryFromCommandLine:
+    case Whence::SecondaryFromFileList:
+      addInput(file);
+      break;
+    }
+  }
+
+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;
+    getFilesFromCommandLine();
+    if (getFilesFromFilelist())
+      return true;
+    return setPrimaryFiles();
+  }
+
+private:
+  bool enforceFilelistExclusion() {
+    if (Args.hasArg(options::OPT_INPUT) && FilelistPathArg != nullptr) {
+      Diags.diagnose(SourceLoc(),
+                     diag::error_cannot_have_input_files_with_file_list);
+      return true;
+    }
+    return false;
+  }
+  void getFilesFromCommandLine() {
+    for (const Arg *A :
+         Args.filtered(options::OPT_INPUT, options::OPT_primary_file)) {
+      StringRef file = A->getValue();
+      if (A->getOption().matches(options::OPT_INPUT))
+        addFile(file, Whence::SecondaryFromCommandLine);
+      else if (A->getOption().matches(options::OPT_primary_file))
+        addFile(file, Whence::PrimaryFromCommandLine);
+      else
+        llvm_unreachable("Unknown input-related argument!");
+    }
+  }
+
+  bool getFilesFromFilelist() {
+    if (FilelistPathArg == nullptr)
+      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);
+    for (auto file : llvm::make_range(llvm::line_iterator(*FilelistBuffer),
+                                      llvm::line_iterator())) {
+      addFile(file, Whence::SecondaryFromFileList);
+    }
+    return false;
+  }
+
+  bool setPrimaryFiles() {
+    for (StringRef primaryFile : PrimaryFiles) {
+      const auto iterator = FileIndices.find(primaryFile);
+      // Catch "swiftc -frontend -c -filelist foo -primary-file
+      // some-file-not-in-foo".
+      if (iterator == FileIndices.end()) {
+        assert(FilelistPathArg != nullptr &&
+               "Missing primary with no filelist");
+        Diags.diagnose(SourceLoc(), diag::error_primary_file_not_found,
+                       primaryFile, filelistPath());
+        return true;
+      }
+      Inputs.addPrimaryInputFilename(iterator->second);
+    }
+    return false;
+  }
+};
+} // namespace swift
+
 // This is a separate function so that it shows up in stack traces.
 LLVM_ATTRIBUTE_NOINLINE
 static void debugFailWithAssertion() {
@@ -224,7 +361,8 @@
     }
   }
 
-  Opts.Inputs.setInputFilenamesAndPrimaryInput(Diags, Args);
+  if (ArgsToFrontendInputsConverter(Diags, Args, Opts.Inputs).convert())
+    return true;
 
   Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
 
@@ -323,7 +461,7 @@
   }
 
   if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
-      Opts.Inputs.hasPrimaryInput()) {
+      Opts.Inputs.havePrimaryInputs()) {
     Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
     return true;
   }
@@ -711,7 +849,7 @@
   if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
     Opts.ImplicitObjCHeaderPath = A->getValue();
     Opts.SerializeBridgingHeader |=
-        !Opts.Inputs.getPrimaryInput() && !Opts.ModuleOutputPath.empty();
+        !Opts.Inputs.havePrimaryInputs() && !Opts.ModuleOutputPath.empty();
   }
 
   for (const Arg *A : Args.filtered(OPT_import_module)) {
@@ -844,12 +982,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 +1100,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,
@@ -1302,8 +1427,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);
@@ -1312,6 +1435,8 @@
   Opts.EnableMandatorySemanticARCOpts |=
       !Args.hasArg(OPT_disable_mandatory_semantic_arc_opts);
   Opts.EnableLargeLoadableTypes |= Args.hasArg(OPT_enable_large_loadable_types);
+  Opts.EnableGuaranteedNormalArguments |=
+      Args.hasArg(OPT_enable_guaranteed_normal_arguments);
 
   if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_path))
     Opts.OptRecordFile = A->getValue();
@@ -1464,11 +1589,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 Optional<StringRef> filename =
+                 FrontendOpts.Inputs.getOptionalUniquePrimaryInputFilename()) {
+    Opts.MainInputFilename = filename.getValue();
+  } else if (FrontendOpts.Inputs.haveUniqueInputFilename()) {
     Opts.MainInputFilename = FrontendOpts.Inputs.getFilenameOfFirstInput();
   }
   Opts.OutputFilenames = FrontendOpts.OutputFilenames;
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 58428fc..ac75c2a 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -157,7 +157,7 @@
     Invocation.getLangOptions().EnableAccessControl = false;
 
   const Optional<SelectedInput> &PrimaryInput =
-      Invocation.getFrontendOptions().Inputs.getPrimaryInput();
+      Invocation.getFrontendOptions().Inputs.getOptionalPrimaryInput();
 
   // Add the memory buffers first, these will be associated with a filename
   // and they can replace the contents of an input filename.
@@ -187,7 +187,7 @@
   for (unsigned i = 0,
                 e = Invocation.getFrontendOptions().Inputs.inputFilenameCount();
        i != e; ++i) {
-    bool hasError = setupForFileAt(i);
+    bool hasError = setUpForFileAt(i);
     if (hasError) {
       return true;
     }
@@ -726,7 +726,7 @@
   PrimarySourceFile = nullptr;
 }
 
-bool CompilerInstance::setupForFileAt(unsigned i) {
+bool CompilerInstance::setUpForFileAt(unsigned i) {
   bool MainMode = (Invocation.getInputKind() == InputFileKind::IFK_Swift);
   bool SILMode = (Invocation.getInputKind() == InputFileKind::IFK_SIL);
 
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index 8bdca8f..8ef2d3d 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 (haveUniqueInputFilename()) {
     StringRef Input(getFilenameOfFirstInput());
     return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
            llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
@@ -43,24 +43,25 @@
     return llvm::sys::path::stem(pifn);
   }
   bool UserSpecifiedModuleName = Args.getLastArg(options::OPT_module_name);
-  if (!UserSpecifiedModuleName && hasUniqueInputFilename()) {
+  if (!UserSpecifiedModuleName && haveUniqueInputFilename()) {
     return llvm::sys::path::stem(getFilenameOfFirstInput());
   }
   return ModuleName;
 }
 
 bool FrontendInputs::shouldTreatAsSIL() const {
-  if (hasUniqueInputFilename()) {
+  if (haveUniqueInputFilename()) {
     // 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.
+  if (const Optional<StringRef> filename =
+          getOptionalUniquePrimaryInputFilename()) {
+    return llvm::sys::path::extension(filename.getValue())
+        .endswith(SIL_EXTENSION);
   }
   return false;
 }
@@ -69,15 +70,15 @@
                                   bool isREPLRequested,
                                   bool isNoneRequested) const {
   if (isREPLRequested) {
-    if (hasInputFilenames()) {
+    if (haveInputFilenames()) {
       Diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
       return true;
     }
-  } else if (TreatAsSIL && hasPrimaryInput()) {
+  } else if (TreatAsSIL && havePrimaryInputs()) {
     // 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)
+      if (i == getOptionalUniquePrimaryInput()->Index)
         continue;
 
       StringRef File(getInputFilenames()[i]);
@@ -88,12 +89,12 @@
       }
     }
   } else if (TreatAsSIL) {
-    if (!hasUniqueInputFilename()) {
+    if (!haveUniqueInputFilename()) {
       Diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
       return true;
     }
   } else if (!isNoneRequested) {
-    if (!hasInputFilenames()) {
+    if (!haveInputFilenames()) {
       Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
       return true;
     }
@@ -108,66 +109,6 @@
   }
 }
 
-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!");
-    }
-  }
-}
-
-/// 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) {
   case ActionType::NoneAction:
@@ -284,7 +225,7 @@
 }
 
 StringRef FrontendOptions::originalPath() const {
-  if (hasNamedOutputFile())
+  if (haveNamedOutputFile())
     // Put the serialized diagnostics file next to the output file.
     return getSingleOutputFilename();
 
@@ -304,7 +245,7 @@
     return "REPL";
   }
   // In order to pass Driver/options.swift test must leave ModuleName empty
-  if (!Inputs.hasInputFilenames()) {
+  if (!Inputs.haveInputFilenames()) {
     return StringRef();
   }
   StringRef OutputFilename = getSingleOutputFilename();
@@ -341,11 +282,11 @@
 }
 
 bool FrontendOptions::isOutputFileDirectory() const {
-  return hasNamedOutputFile() &&
+  return haveNamedOutputFile() &&
          llvm::sys::fs::is_directory(getSingleOutputFilename());
 }
 
 bool FrontendOptions::isOutputFilePlainFile() const {
-  return hasNamedOutputFile() &&
+  return haveNamedOutputFile() &&
          !llvm::sys::fs::is_directory(getSingleOutputFilename());
 }
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index d6acb03..105179d 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"
@@ -542,7 +541,7 @@
     auto &LLVMContext = getGlobalLLVMContext();
 
     // Load in bitcode file.
-    assert(Invocation.getFrontendOptions().Inputs.hasUniqueInputFilename() &&
+    assert(Invocation.getFrontendOptions().Inputs.haveUniqueInputFilename() &&
            "We expect a single input for bitcode input!");
     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
         llvm::MemoryBuffer::getFileOrSTDIN(
@@ -780,7 +779,7 @@
     if (opts.Inputs.haveAPrimaryInputFile()) {
       FileUnit *PrimaryFile = PrimarySourceFile;
       if (!PrimaryFile) {
-        auto Index = opts.Inputs.getPrimaryInput().getValue().Index;
+        auto Index = opts.Inputs.getRequiredUniquePrimaryInput().Index;
         PrimaryFile = Instance.getMainModule()->getFiles()[Index];
       }
       astGuaranteedToCorrespondToSIL = !fileIsSIB(PrimaryFile);
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index b61ca6d..0c31ecc 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");
     }
@@ -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..2496ed5 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -322,6 +322,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 +2108,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 +2309,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..057d50a 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
@@ -2329,7 +2380,7 @@
     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";
@@ -2352,7 +2403,7 @@
     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";
@@ -2422,7 +2473,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));
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 5c0fff3..d2c5485 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);
@@ -3583,6 +3580,15 @@
                                       /*allowUninit*/ false)) {
         HasUnfilledSuperclass = true;
       }
+      
+      // 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,
+                                 superclassTy->getClassOrBoundGenericClass())) {
+        HasUnfilledSuperclass = true;
+      }
     }
 
     bool canBeConstant() {
@@ -3933,7 +3939,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,10 +4061,13 @@
                                                 llvm::Value *metadata) {
   // FIXME: The below checks should capture this property already, but
   // resilient class metadata layout is not fully implemented yet.
-  auto expansion = IGF.IGM.getResilienceExpansionForLayout(theClass);
-  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.
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index 51f96f8..e5d75d1 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -188,6 +188,17 @@
   auto call = IGF.Builder.CreateCall(fn, value);
   call->setDoesNotThrow();
 
+  const llvm::Triple &triple = IGF.IGM.Context.LangOpts.Target;
+  if (triple.getArch() == llvm::Triple::x86_64) {
+    // Don't tail call objc_retainAutoreleasedReturnValue. This blocks the
+    // autoreleased return optimization.
+    // callq  0x01ec08 ; symbol stub for: objc_msgSend
+    // movq   %rax, %rdi
+    // popq   %rbp  ;<== Blocks the handshake from objc_autoreleaseReturnValue
+    // jmp    0x01ec20 ; symbol stub for: objc_retainAutoreleasedReturnValue
+    call->setTailCallKind(llvm::CallInst::TCK_NoTail);
+  }
+
   llvm::Value *result = call;
   if (isa<llvm::PointerType>(valueType)) {
     result = IGF.Builder.CreateBitCast(result, valueType);
@@ -318,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);
 
@@ -353,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);
@@ -415,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..a93a908 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -769,7 +769,7 @@
     OS << ".sw3" << FourCC;
     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/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/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 430fb0a..71f52c5 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;
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index cbada81..8103061 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1473,10 +1473,9 @@
 void IRGenModule::emitSILFunction(SILFunction *f) {
   if (f->isExternalDeclaration())
     return;
+
   // Do not emit bodies of public_external functions.
-  // The only exception is transparent functions.
-  if (hasPublicVisibility(f->getLinkage()) && f->isAvailableExternally() &&
-      !f->isTransparent())
+  if (hasPublicVisibility(f->getLinkage()) && f->isAvailableExternally())
     return;
 
   PrettyStackTraceSILFunction stackTrace("emitting IR", f);
@@ -1633,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;
@@ -3497,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.
@@ -3521,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) {
@@ -5033,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();
@@ -5097,7 +5083,6 @@
   SILType addrTy = i->getOperand()->getType();
   const TypeInfo &addrTI = getTypeInfo(addrTy);
 
-  // Otherwise, do the normal thing.
   Address base = getLoweredAddress(i->getOperand());
   addrTI.destroy(*this, base, addrTy, false /*isOutlined*/);
 }
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 80c2e9b..411589e 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);
@@ -2605,7 +2615,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);
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/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/Migrator/CMakeLists.txt b/lib/Migrator/CMakeLists.txt
index afc48a7..437fb64 100644
--- a/lib/Migrator/CMakeLists.txt
+++ b/lib/Migrator/CMakeLists.txt
@@ -44,6 +44,8 @@
   RewriteBufferEditsReceiver.cpp
   TupleSplatMigratorPass.cpp
   TypeOfMigratorPass.cpp
+  DEPENDS
+    swift-syntax-generated-headers
   LINK_LIBRARIES swiftSyntax swiftIDE)
 
 add_dependencies(swiftMigrator
diff --git a/lib/Migrator/Migrator.cpp b/lib/Migrator/Migrator.cpp
index 2808540..654721c 100644
--- a/lib/Migrator/Migrator.cpp
+++ b/lib/Migrator/Migrator.cpp
@@ -447,8 +447,8 @@
 }
 
 const StringRef Migrator::getInputFilename() const {
-  auto PrimaryInput =
-      StartInvocation.getFrontendOptions().Inputs.getPrimaryInput().getValue();
+  auto PrimaryInput = StartInvocation.getFrontendOptions()
+                          .Inputs.getRequiredUniquePrimaryInput();
   return StartInvocation.getFrontendOptions()
       .Inputs.getInputFilenames()[PrimaryInput.Index];
 }
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 37a48c8..5ff63a4 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -738,25 +738,6 @@
   return false;
 }
 
-syntax::RawSyntaxInfo Lexer::fullLex() {
-  if (NextToken.isEscapedIdentifier()) {
-    LeadingTrivia.push_back(syntax::TriviaPiece::backtick());
-    TrailingTrivia.insert(TrailingTrivia.begin(),
-                          syntax::TriviaPiece::backtick());
-  }
-  auto Loc = NextToken.getLoc();
-  auto Result = syntax::RawTokenSyntax::make(NextToken.getKind(),
-                                        OwnedString(NextToken.getText()),
-                                        syntax::SourcePresence::Present,
-                                        {LeadingTrivia}, {TrailingTrivia});
-  LeadingTrivia.clear();
-  TrailingTrivia.clear();
-  if (NextToken.isNot(tok::eof)) {
-    lexImpl();
-  }
-  return {Loc, Result};
-}
-
 /// lexOperatorIdentifier - Match identifiers formed out of punctuation.
 void Lexer::lexOperatorIdentifier() {
   const char *TokStart = CurPtr-1;
@@ -2366,6 +2347,7 @@
   switch (Last) {
     case '\n':
     case '\r':
+      NextToken.setAtStartOfLine(true);
       return syntax::TriviaPiece {
         syntax::TriviaKind::Newline,
         Length,
@@ -2463,10 +2445,18 @@
   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;
     }
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5595983..452c9c7 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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;
 }
 
@@ -2191,8 +2200,9 @@
 ParserResult<Decl>
 Parser::parseDecl(ParseDeclOptions Flags,
                   llvm::function_ref<void(Decl*)> Handler) {
-  SyntaxParsingContextChild DeclParsingContext(SyntaxContext,
-                                               SyntaxContextKind::Decl);
+  SyntaxParsingContext DeclParsingContext(SyntaxContext,
+                                          SyntaxContextKind::Decl);
+
   if (Tok.is(tok::pound_if)) {
     auto IfConfigResult = parseIfConfig(
       [&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
@@ -2262,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)
@@ -2274,7 +2284,7 @@
       }
       consumeToken(tok::kw_static);
       continue;
-
+    }
     // 'class' is a modifier on func, but is also a top-level decl.
     case tok::kw_class: {
       SourceLoc ClassLoc = consumeToken(tok::kw_class);
@@ -2301,84 +2311,58 @@
     case tok::kw_private:
     case tok::kw_fileprivate:
     case tok::kw_internal:
-    case tok::kw_public:
+    case tok::kw_public: {
       // 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) {
+        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:
@@ -2926,6 +2910,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, ";")
@@ -2970,15 +2955,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
@@ -5383,7 +5370,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;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 46bfa7d..817deb6 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -40,8 +40,7 @@
 /// \param isExprBasic Whether we're only parsing an expr-basic.
 ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) {
   // Start a context for creating expression syntax.
-  SyntaxParsingContextChild ExprParsingContext(SyntaxContext,
-                                               SyntaxContextKind::Expr);
+  SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr);
 
   // If we are parsing a refutable pattern, check to see if this is the start
   // of a let/var/is pattern.  If so, parse it to an UnresolvedPatternExpr and
@@ -165,8 +164,8 @@
 ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
                                              bool isExprBasic,
                                              bool isForConditionalDirective) {
-  SyntaxParsingContextChild ExprSequnceContext(SyntaxContext,
-                                               SyntaxContextKind::Expr);
+  SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr);
+
   SmallVector<Expr*, 8> SequencedExprs;
   SourceLoc startLoc = Tok.getLoc();
   bool HasCodeCompletion = false;
@@ -194,7 +193,7 @@
 
     // We know we can make a syntax node for ternary expression.
     if (PendingTernary) {
-      SyntaxContext->makeNode(SyntaxKind::TernaryExpr, Tok.getLoc());
+      SyntaxContext->createNodeInPlace(SyntaxKind::TernaryExpr);
       PendingTernary = false;
     }
 
@@ -218,6 +217,8 @@
         goto done;
       
       // Parse the operator.
+      SyntaxParsingContext OperatorContext(SyntaxContext,
+                                           SyntaxKind::BinaryOperatorExpr);
       Expr *Operator = parseExprOperator();
       SequencedExprs.push_back(Operator);
       
@@ -268,7 +269,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);
@@ -299,6 +301,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())
@@ -315,6 +318,7 @@
     }
         
     case tok::kw_as: {
+      SyntaxParsingContext AsContext(SyntaxContext, SyntaxKind::AsExpr);
       ParserResult<Expr> as = parseExprAs();
       if (as.isNull() || as.hasCodeCompletion())
         return as;
@@ -363,6 +367,8 @@
     return Result;
   }
 
+  ExprSequnceContext.createNodeInPlace(SyntaxKind::ExprList);
+  ExprSequnceContext.setCreateSyntax(SyntaxKind::SequenceExpr);
   auto Result = makeParserResult(SequenceExpr::create(Context, SequencedExprs));
   if (HasCodeCompletion)
     Result.setHasCodeCompletion();
@@ -381,8 +387,8 @@
 /// sequence, but this isn't enforced until sequence-folding.
 ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
                                                     bool isExprBasic) {
-  SyntaxParsingContextChild ElementContext(SyntaxContext,
-                                           SyntaxContextKind::Expr);
+  SyntaxParsingContext ElementContext(SyntaxContext,
+                                      SyntaxContextKind::Expr);
   SourceLoc tryLoc;
   bool hadTry = consumeIf(tok::kw_try, tryLoc);
   Optional<Token> trySuffix;
@@ -457,6 +463,7 @@
 ///     '&' expr-unary(Mode)
 ///
 ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
+  SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr);
   UnresolvedDeclRefExpr *Operator;
   switch (Tok.getKind()) {
   default:
@@ -512,6 +519,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())) {
@@ -568,7 +578,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);
 
@@ -1183,7 +1193,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));
@@ -1400,12 +1410,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->makeNode(SyntaxKind::IntegerLiteralExpr, Tok.getLoc());
+    SyntaxContext->setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
     Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1413,7 +1448,7 @@
   case tok::floating_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::floating_literal);
-    SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Tok.getLoc());
+    SyntaxContext->setCreateSyntax(SyntaxKind::FloatLiteralExpr);
     Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1435,7 +1470,7 @@
     break;
   
   case tok::kw_nil: {
-    SyntaxParsingContextChild NilContext(SyntaxContext, SyntaxKind::NilLiteralExpr);
+    SyntaxParsingContext NilContext(SyntaxContext, SyntaxKind::NilLiteralExpr);
     Result = makeParserResult(
                       new (Context) NilLiteralExpr(consumeToken(tok::kw_nil)));
     break;
@@ -1443,8 +1478,8 @@
 
   case tok::kw_true:
   case tok::kw_false: {
-    SyntaxParsingContextChild BoolContext(SyntaxContext,
-                                          SyntaxKind::BooleanLiteralExpr);
+    SyntaxParsingContext BoolContext(SyntaxContext,
+                                     SyntaxKind::BooleanLiteralExpr);
     bool isTrue = Tok.is(tok::kw_true);
     Result = makeParserResult(
                new (Context) BooleanLiteralExpr(isTrue, consumeToken()));
@@ -1526,8 +1561,8 @@
     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()));
     Result = makeParserResult(expr);
     break;
   }
@@ -1538,8 +1573,8 @@
 
     // If the next token is '_', parse a discard expression.
   case tok::kw__: {
-    SyntaxParsingContextChild DAContext(SyntaxContext,
-                                        SyntaxKind::DiscardAssignmentExpr);
+    SyntaxParsingContext DAContext(SyntaxContext,
+                                   SyntaxKind::DiscardAssignmentExpr);
     Result = makeParserResult(
       new (Context) DiscardAssignmentExpr(consumeToken(), /*Implicit=*/false));
     break;
@@ -1678,11 +1713,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;
@@ -1708,7 +1749,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;
@@ -1780,24 +1822,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;
 }
 
@@ -1821,17 +1845,14 @@
 ///   expr-literal:
 ///     string_literal
 ParserResult<Expr> Parser::parseExprStringLiteral() {
+  SyntaxParsingContext LocalContext(SyntaxContext,
+                                    SyntaxKind::StringLiteralExpr);
 
   SmallVector<Lexer::StringSegment, 1> Segments;
   L->getStringLiteralSegments(Tok, Segments);
 
   Token EntireTok = Tok;
 
-  // Create a syntax node for string literal.
-  SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, peekToken().getLoc());
-
-  // FIXME: Avoid creating syntax nodes for string interpolation.
-  SyntaxParsingContextChild LocalContext(SyntaxContext, /*disabled*/true);
 
   // The start location of the entire string literal.
   SourceLoc Loc = Tok.getLoc();
@@ -1844,9 +1865,24 @@
         createStringLiteralExprFromSegment(Context, L, Segments.front(), Loc));
   }
 
+  // FIXME: Properly handle string interpolation.
+  // e.g. /*c*/"foo\(12)bar" should be something like (braces are trivia):
+  //   <InterpolatedStringExpr>
+  //     <InterpolatedStringLiteral>{/*c*/}{"}foo{\}</InterpolatedStringLiteral>
+  //     <ParenExpr>(<IntergerLiteralExpr>12</IntegerLiteralExpr>)</ParentExpr>
+  //     <InterpolatedStringLiteral>bar{"}</InterpolatedStringLiteral>
+  //   </InterpolatedStringExpr>
+  SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
+
   // We don't expose the entire interpolated string as one token. Instead, we
   // should expose the tokens in each segment.
   consumeTokenWithoutFeedingReceiver();
+  // We are going to mess with Tok to do reparsing for interpolated literals,
+  // don't lose our 'next' token.
+  llvm::SaveAndRestore<Token> SavedTok(Tok);
+  llvm::SaveAndRestore<Trivia> SavedLeadingTrivia(LeadingTrivia);
+  llvm::SaveAndRestore<Trivia> SavedTrailingTrivia(TrailingTrivia);
+
   ParserStatus Status;
   SmallVector<Expr*, 4> Exprs;
   bool First = true;
@@ -1878,9 +1914,10 @@
     }
         
     case Lexer::StringSegment::Expr: {
-      // We are going to mess with Tok to do reparsing for interpolated literals,
-      // don't lose our 'next' token.
-      llvm::SaveAndRestore<Token> SavedTok(Tok);
+      // FIXME: Properly handle string interpolation.
+      // For now, discard all nodes inside the literal.
+      SyntaxParsingContext TmpContext(SyntaxContext);
+      TmpContext.setDiscard();
 
       // Create a temporary lexer that lexes from the body of the string.
       Lexer::State BeginState =
@@ -2018,7 +2055,8 @@
   while (true) {
     // The following code may backtrack; so we disable the syntax tree creation
     // in this scope.
-    SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
+    SyntaxParsingContext DisabledContext(SyntaxContext);
+    SyntaxContext->disable();
 
     // Terminate at ')'.
     if (Tok.is(tok::r_paren)) {
@@ -2079,8 +2117,8 @@
 ///     unqualified-decl-name generic-args?
 Expr *Parser::parseExprIdentifier() {
   assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
-  SyntaxParsingContextChild IDSyntaxContext(SyntaxContext,
-                                            SyntaxKind::IdentifierExpr);
+  SyntaxParsingContext IDSyntaxContext(SyntaxContext,
+                                       SyntaxKind::IdentifierExpr);
   Token IdentTok = Tok;
 
   // Parse the unqualified-decl-name.
@@ -2170,7 +2208,7 @@
 
 Expr *Parser::parseExprEditorPlaceholder(Token PlaceholderTok,
                                          Identifier PlaceholderId) {
-  SyntaxParsingContextChild DisableContext(SyntaxContext, /*disabled*/true);
+  SyntaxParsingContext TmpContext(SyntaxContext, SyntaxKind::UnknownExpr);
   assert(PlaceholderTok.is(tok::identifier));
   assert(PlaceholderId.isEditorPlaceholder());
 
@@ -2855,8 +2893,8 @@
     ParserStatus Status;
     Expr *SubExpr = nullptr;
     if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
-      SyntaxParsingContextChild operatorContext(SyntaxContext,
-                                                SyntaxContextKind::Expr);
+      SyntaxParsingContext operatorContext(SyntaxContext,
+                                           SyntaxContextKind::Expr);
       SourceLoc Loc;
       Identifier OperName;
       if (parseAnyIdentifier(OperName, Loc, diag::expected_operator_ref)) {
@@ -3117,7 +3155,7 @@
 ///     expr-dictionary
 //      lsquare-starting ']'
 ParserResult<Expr> Parser::parseExprCollection(SourceLoc LSquareLoc) {
-  SyntaxParsingContextChild ArrayOrDictContext(SyntaxContext);
+  SyntaxParsingContext ArrayOrDictContext(SyntaxContext);
 
   // If the caller didn't already consume the '[', do so now.
   if (LSquareLoc.isInvalid())
@@ -3130,8 +3168,8 @@
   // [] is always an array.
   if (Tok.is(tok::r_square)) {
     // FIXME: Handle empty array syntax node.
-    ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
     SourceLoc RSquareLoc = consumeToken(tok::r_square);
+    ArrayOrDictContext.setCreateSyntax(SyntaxKind::ArrayExpr);
     return makeParserResult(
                     ArrayExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
   }
@@ -3139,9 +3177,9 @@
   // [:] is always an empty dictionary.
   if (Tok.is(tok::colon) && peekToken().is(tok::r_square)) {
     // FIXME: Handle empty dictionary syntax node.
-    ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
     consumeToken(tok::colon);
     SourceLoc RSquareLoc = consumeToken(tok::r_square);
+    ArrayOrDictContext.setCreateSyntax(SyntaxKind::DictionaryExpr);
     return makeParserResult(
                   DictionaryExpr::create(Context, LSquareLoc, {}, RSquareLoc));
   }
@@ -3149,8 +3187,6 @@
   bool ParseDict;
   {
     BacktrackingScope Scope(*this);
-    // Disable the syntax tree creation in the context.
-    SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
     auto HasDelayedDecl = State->hasDelayedDecl();
     // Parse the first expression.
     ParserResult<Expr> FirstExpr
@@ -3160,7 +3196,7 @@
       if (Tok.is(tok::r_square))
         consumeToken();
       Scope.cancelBacktrack();
-      ArrayOrDictContext.setContextKind(SyntaxContextKind::Expr);
+      ArrayOrDictContext.setCoerceKind(SyntaxContextKind::Expr);
       return FirstExpr;
     }
     if (!HasDelayedDecl)
@@ -3168,11 +3204,12 @@
     // If we have a ':', this is a dictionary literal.
     ParseDict = Tok.is(tok::colon);
   }
+
   if (ParseDict) {
-    ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
+    ArrayOrDictContext.setCreateSyntax(SyntaxKind::DictionaryExpr);
     return parseExprDictionary(LSquareLoc);
   } else {
-    ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
+    ArrayOrDictContext.setCreateSyntax(SyntaxKind::ArrayExpr);
     return parseExprArray(LSquareLoc);
   }
 }
diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp
index 141e40f..d5f83da 100644
--- a/lib/Parse/ParseGeneric.cpp
+++ b/lib/Parse/ParseGeneric.cpp
@@ -18,6 +18,9 @@
 #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;
 
 /// parseGenericParameters - Parse a sequence of generic parameters, e.g.,
@@ -248,7 +251,10 @@
   FirstTypeInComplete = false;
   do {
     // 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();
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/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 9403bbf..9a685c6 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -226,7 +226,8 @@
 ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
                                      BraceItemListKind Kind,
                                      BraceItemListKind ConditionalBlockKind) {
-  SyntaxParsingContextChild StmtListContext(SyntaxContext, SyntaxKind::StmtList);
+  SyntaxParsingContext StmtListContext(SyntaxContext, SyntaxKind::StmtList);
+
   bool IsTopLevel = (Kind == BraceItemListKind::TopLevelCode) ||
                     (Kind == BraceItemListKind::TopLevelLibrary);
   bool isActiveConditionalBlock =
@@ -262,7 +263,9 @@
          Tok.isNot(tok::kw_sil_default_witness_table) &&
          (isConditionalBlock ||
           !isTerminatorForBraceItemListKind(Kind, Entries))) {
-    SyntaxParsingContextChild StmtContext(SyntaxContext, SyntaxContextKind::Stmt);
+
+    SyntaxParsingContext StmtContext(SyntaxContext, SyntaxContextKind::Stmt);
+
     if (Kind == BraceItemListKind::TopLevelLibrary &&
         skipExtraTopLevelRBraces())
       continue;
@@ -493,7 +496,8 @@
 }
 
 ParserResult<Stmt> Parser::parseStmt() {
-  SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
+  SyntaxParsingContext LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
+
   // Note that we're parsing a statement.
   StructureMarkerRAII ParsingStmt(*this, Tok.getLoc(),
                                   StructureMarkerKind::Statement);
@@ -590,7 +594,7 @@
     if (Tok.isNot(tok::l_brace))
       return nullptr;
   }
-  SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
+  SyntaxParsingContext LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
   SourceLoc LBLoc = consumeToken(tok::l_brace);
 
   SmallVector<ASTNode, 16> Entries;
@@ -656,7 +660,7 @@
 ///     'return' expr?
 ///   
 ParserResult<Stmt> Parser::parseStmtReturn(SourceLoc tryLoc) {
-  SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::ReturnStmt);
+  SyntaxParsingContext LocalContext(SyntaxContext, SyntaxKind::ReturnStmt);
   SourceLoc ReturnLoc = consumeToken(tok::kw_return);
 
   if (Tok.is(tok::code_complete)) {
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 b90d5f8..c704176 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -19,6 +19,7 @@
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/DiagnosticsParse.h"
 #include "swift/AST/PrettyStackTrace.h"
+#include "swift/Basic/Defer.h"
 #include "swift/Basic/SourceManager.h"
 #include "swift/Basic/Timer.h"
 #include "swift/Parse/Lexer.h"
@@ -235,9 +236,10 @@
   }
 
   std::vector<Token> Tokens;
+  Trivia LeadingTrivia, TrailingTrivia;
   do {
     Tokens.emplace_back();
-    L.lex(Tokens.back());
+    L.lex(Tokens.back(), LeadingTrivia, TrailingTrivia);
 
     // If the token has the same location as a reset location,
     // reset the token stream
@@ -280,8 +282,18 @@
   std::vector<std::pair<RC<syntax::RawTokenSyntax>,
                         syntax::AbsolutePosition>> Tokens;
   syntax::AbsolutePosition RunningPos;
+  Token Tok;
+  Trivia LeadingTrivia, TrailingTrivia;
   do {
-    auto ThisToken = L.fullLex().getRaw<syntax::RawTokenSyntax>();
+    L.lex(Tok, LeadingTrivia, TrailingTrivia);
+    if (Tok.isEscapedIdentifier()) {
+      LeadingTrivia.push_back(TriviaPiece::backtick());
+      TrailingTrivia.push_front(TriviaPiece::backtick());
+    }
+    auto ThisToken = RawTokenSyntax::make(Tok.getKind(), Tok.getText(),
+                                      SourcePresence::Present, LeadingTrivia,
+                                      TrailingTrivia);
+
     auto ThisTokenPos = ThisToken->accumulateAbsolutePosition(RunningPos);
     Tokens.push_back({ThisToken, ThisTokenPos});
   } while (Tokens.back().first->isNot(tok::eof));
@@ -289,36 +301,24 @@
   return Tokens;
 }
 
-void swift::populateTokenSyntaxMap(const LangOptions &LangOpts,
-                                   const SourceManager &SM,
-                                   unsigned BufferID,
-                                   std::vector<syntax::RawSyntaxInfo> &Result) {
-  if (!Result.empty())
-    return;
-  Lexer L(LangOpts, SM, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
-          CommentRetentionMode::AttachToNextToken,
-          TriviaRetentionMode::WithTrivia);
-  do {
-    Result.emplace_back(L.fullLex());
-    if (Result.back().getRaw<syntax::RawTokenSyntax>()->is(tok::eof))
-      return;
-  } while (true);
-}
-
 //===----------------------------------------------------------------------===//
 // Setup and Helper Methods
 //===----------------------------------------------------------------------===//
 
 Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
                PersistentParserState *PersistentState)
-  : Parser(std::unique_ptr<Lexer>(
-             new Lexer(SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
-                   BufferID, &SF.getASTContext().Diags,
-                   /*InSILMode=*/SIL != nullptr,
-                   SF.getASTContext().LangOpts.AttachCommentsToDecls
-                   ? CommentRetentionMode::AttachToNextToken
-                   : CommentRetentionMode::None)), SF, SIL, PersistentState){
-}
+    : Parser(
+          std::unique_ptr<Lexer>(new Lexer(
+              SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
+              BufferID, &SF.getASTContext().Diags,
+              /*InSILMode=*/SIL != nullptr,
+              SF.getASTContext().LangOpts.AttachCommentsToDecls
+                  ? CommentRetentionMode::AttachToNextToken
+                  : CommentRetentionMode::None,
+              SF.shouldKeepSyntaxInfo()
+                  ? TriviaRetentionMode::WithTrivia
+                  : TriviaRetentionMode::WithoutTrivia)),
+          SF, SIL, PersistentState) {}
 
 namespace {
 
@@ -447,8 +447,7 @@
     TokReceiver(SF.shouldKeepSyntaxInfo() ?
                 new TokenRecorder(SF) :
                 new ConsumeTokenReceiver()),
-    SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(),
-                                                       Tok)) {
+    SyntaxContext(new SyntaxParsingContext(SyntaxContext, SF)) {
   State = PersistentState;
   if (!State) {
     OwnedState.reset(new PersistentParserState());
@@ -469,6 +468,9 @@
 }
 
 Parser::~Parser() {
+  if (Tok.is(tok::eof))
+    SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
+
   delete L;
   delete TokReceiver;
   delete SyntaxContext;
@@ -485,7 +487,7 @@
   if (IsParsingInterfaceTokens && !Tok.getText().empty()) {
     SF.recordInterfaceToken(Tok.getText());
   }
-  L->lex(Tok);
+  L->lex(Tok, LeadingTrivia, TrailingTrivia);
   PreviousLoc = Loc;
   return Loc;
 }
@@ -496,6 +498,7 @@
 
 SourceLoc Parser::consumeToken() {
   TokReceiver->receive(Tok);
+  SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
   return consumeTokenWithoutFeedingReceiver();
 }
 
@@ -510,16 +513,17 @@
   return ParserPosition(NewState, Loc);
 }
 
-SourceLoc Parser::consumeStartingCharacterOfCurrentToken() {
+SourceLoc Parser::consumeStartingCharacterOfCurrentToken(tok Kind) {
   // Consumes one-character token (like '?', '<', '>' or '!') and returns
   // its location.
 
   // Current token can be either one-character token we want to consume...
   if (Tok.getLength() == 1) {
+    Tok.setKind(Kind);
     return consumeToken();
   }
 
-  markSplitToken(tok::oper_binary_unspaced, Tok.getText().substr(0, 1));
+  markSplitToken(Kind, Tok.getText().substr(0, 1));
 
   // ... or a multi-character token with the first character being the one that
   // we want to consume as a separate token.
@@ -531,16 +535,20 @@
 void Parser::markSplitToken(tok Kind, StringRef Txt) {
   SplitTokens.emplace_back();
   SplitTokens.back().setToken(Kind, Txt);
+  Trivia EmptyTrivia;
+  SyntaxContext->addToken(SplitTokens.back(), LeadingTrivia, EmptyTrivia);
+  LeadingTrivia.empty();
+  TokReceiver->receive(SplitTokens.back());
 }
 
 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() {
@@ -826,7 +834,7 @@
   return false;
 }
 
-static Optional<SyntaxKind> getListElementKind(SyntaxKind ListKind) {
+static SyntaxKind getListElementKind(SyntaxKind ListKind) {
   switch (ListKind) {
   case SyntaxKind::FunctionCallArgumentList:
     return SyntaxKind::FunctionCallArgument;
@@ -834,8 +842,10 @@
     return SyntaxKind::ArrayElement;
   case SyntaxKind::DictionaryElementList:
     return SyntaxKind::DictionaryElement;
+  case SyntaxKind::TupleElementList:
+    return SyntaxKind::TupleElement;
   default:
-    return None;
+    return SyntaxKind::Unknown;
   }
 }
 
@@ -843,16 +853,12 @@
 Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
                   bool AllowSepAfterLast, Diag<> ErrorDiag, SyntaxKind Kind,
                   std::function<ParserStatus()> callback) {
-  SyntaxParsingContextChild ListContext(SyntaxContext);
-  Optional<SyntaxKind> ElementKind = getListElementKind(Kind);
-  if (ElementKind)
-    ListContext.setSyntaxKind(Kind);
-  else
-    // FIXME: we shouldn't need this when all cases are handled.
-    ListContext.disable();
+  llvm::Optional<SyntaxParsingContext> ListContext;
+  ListContext.emplace(SyntaxContext, Kind);
+
+  SyntaxKind ElementKind = getListElementKind(Kind);
 
   if (Tok.is(RightK)) {
-    ListContext.finalize();
     RightLoc = consumeToken(RightK);
     return makeParserSuccess();
   }
@@ -865,12 +871,9 @@
       consumeToken();
     }
     SourceLoc StartLoc = Tok.getLoc();
-    SyntaxParsingContextChild ElementContext(SyntaxContext);
-    if (ElementKind) {
-      ElementContext.setSyntaxKind(*ElementKind);
-    } else {
-      ElementContext.disable();
-    }
+
+    SyntaxParsingContext ElementContext(SyntaxContext, ElementKind);
+
     Status |= callback();
     if (Tok.is(RightK))
       break;
@@ -914,7 +917,8 @@
     Status.setIsParseError();
   }
 
-  ListContext.finalize();
+  ListContext.reset();
+
   if (Status.isError()) {
     // If we've already got errors, don't emit missing RightK diagnostics.
     RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
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/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index aa65f47..43f9a26 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -10,8 +10,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "swift/AST/Expr.h"
 #include "swift/SIL/SILBuilder.h"
+#include "swift/AST/Expr.h"
+#include "swift/SIL/Projection.h"
 #include "swift/SIL/SILGlobalVariable.h"
 
 using namespace swift;
@@ -459,3 +460,52 @@
   return insert(new (getModule()) ValueMetatypeInst(getSILDebugLocation(Loc),
                                                       MetatypeTy, Base));
 }
+
+// TODO: This should really be an operation on type lowering.
+void SILBuilder::emitShallowDestructureValueOperation(
+    SILLocation Loc, SILValue V, llvm::SmallVectorImpl<SILValue> &Results) {
+  // Once destructure is allowed everywhere, remove the projection code.
+
+  // If we do not have a tuple or a struct, add to our results list and return.
+  SILType Ty = V->getType();
+  if (!(Ty.is<TupleType>() || Ty.getStructOrBoundGenericStruct())) {
+    Results.emplace_back(V);
+    return;
+  }
+
+  // Otherwise, we want to destructure add the destructure and return.
+  if (getFunction().hasQualifiedOwnership()) {
+    auto *DI = emitDestructureValueOperation(Loc, V);
+    copy(DI->getResults(), std::back_inserter(Results));
+    return;
+  }
+
+  // In non qualified ownership SIL, drop back to using projection code.
+  llvm::SmallVector<Projection, 16> Projections;
+  Projection::getFirstLevelProjections(V->getType(), getModule(), Projections);
+  transform(Projections, std::back_inserter(Results),
+            [&](const Projection &P) -> SILValue {
+              return P.createObjectProjection(*this, Loc, V).get();
+            });
+}
+
+// TODO: Can we put this on type lowering? It would take a little bit of work
+// since we would need to be able to handle aggregate trivial types which is not
+// represented today in TypeLowering.
+void SILBuilder::emitShallowDestructureAddressOperation(
+    SILLocation Loc, SILValue V, llvm::SmallVectorImpl<SILValue> &Results) {
+
+  // If we do not have a tuple or a struct, add to our results list.
+  SILType Ty = V->getType();
+  if (!(Ty.is<TupleType>() || Ty.getStructOrBoundGenericStruct())) {
+    Results.emplace_back(V);
+    return;
+  }
+
+  llvm::SmallVector<Projection, 16> Projections;
+  Projection::getFirstLevelProjections(V->getType(), getModule(), Projections);
+  transform(Projections, std::back_inserter(Results),
+            [&](const Projection &P) -> SILValue {
+              return P.createAddressProjection(*this, Loc, V).get();
+            });
+}
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 494f4f2..1ddfd37 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -484,6 +484,12 @@
   return dyn_cast<FuncDecl>(getDecl());
 }
 
+bool SILDeclRef::isSetter() const {
+  if (!hasFuncDecl())
+    return false;
+  return getFuncDecl()->isSetter();
+}
+
 AbstractFunctionDecl *SILDeclRef::getAbstractFunctionDecl() const {
   return dyn_cast<AbstractFunctionDecl>(getDecl());
 }
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 369ba49..df4876f 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -237,7 +237,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;
@@ -740,6 +740,119 @@
   return (classDecl && classDecl->usesObjCGenericsModel());
 }
 
+/// Update the result type given the foreign error convention that we will be
+/// using.
+static std::pair<AbstractionPattern, CanType> updateResultTypeForForeignError(
+    ForeignErrorConvention convention, CanGenericSignature genericSig,
+    AbstractionPattern origResultType, CanType substFormalResultType) {
+  switch (convention.getKind()) {
+  // These conventions replace the result type.
+  case ForeignErrorConvention::ZeroResult:
+  case ForeignErrorConvention::NonZeroResult:
+    assert(substFormalResultType->isVoid());
+    substFormalResultType = convention.getResultType();
+    origResultType = AbstractionPattern(genericSig, substFormalResultType);
+    return {origResultType, substFormalResultType};
+
+  // These conventions wrap the result type in a level of optionality.
+  case ForeignErrorConvention::NilResult:
+    assert(!substFormalResultType->getAnyOptionalObjectType());
+    substFormalResultType =
+        OptionalType::get(substFormalResultType)->getCanonicalType();
+    origResultType =
+        AbstractionPattern::getOptional(origResultType, OTK_Optional);
+    return {origResultType, substFormalResultType};
+
+  // These conventions don't require changes to the formal error type.
+  case ForeignErrorConvention::ZeroPreservedResult:
+  case ForeignErrorConvention::NonNilError:
+    return {origResultType, substFormalResultType};
+  }
+}
+
+/// Lower any/all capture context parameters.
+///
+/// *NOTE* Currently default arg generators can not capture anything.
+/// If we ever add that ability, it will be a different capture list
+/// from the function to which the argument is attached.
+static void
+lowerCaptureContextParameters(SILModule &M, AnyFunctionRef function,
+                              CanGenericSignature genericSig,
+                              SmallVectorImpl<SILParameterInfo> &inputs) {
+
+  // NB: The generic signature may be elided from the lowered function type
+  // if the function is in a fully-specialized context, but we still need to
+  // canonicalize references to the generic parameters that may appear in
+  // non-canonical types in that context. We need the original generic
+  // signature from the AST for that.
+  auto origGenericSig = function.getGenericSignature();
+
+  auto &Types = M.Types;
+  auto loweredCaptures = Types.getLoweredLocalCaptures(function);
+
+  for (auto capture : loweredCaptures.getCaptures()) {
+    if (capture.isDynamicSelfMetadata()) {
+      ParameterConvention convention = ParameterConvention::Direct_Unowned;
+      auto dynamicSelfInterfaceType =
+          loweredCaptures.getDynamicSelfType()->mapTypeOutOfContext();
+
+      auto selfMetatype = MetatypeType::get(dynamicSelfInterfaceType,
+                                            MetatypeRepresentation::Thick);
+
+      auto canSelfMetatype = selfMetatype->getCanonicalType(origGenericSig);
+      SILParameterInfo param(canSelfMetatype, convention);
+      inputs.push_back(param);
+
+      continue;
+    }
+
+    auto *VD = capture.getDecl();
+    auto type = VD->getInterfaceType();
+    auto canType = type->getCanonicalType(origGenericSig);
+
+    auto &loweredTL =
+        Types.getTypeLowering(AbstractionPattern(genericSig, canType), canType);
+    auto loweredTy = loweredTL.getLoweredType();
+    switch (Types.getDeclCaptureKind(capture)) {
+    case CaptureKind::None:
+      break;
+    case CaptureKind::Constant: {
+      // Constants are captured by value.
+      ParameterConvention convention;
+      if (loweredTL.isAddressOnly()) {
+        convention = ParameterConvention::Indirect_In_Guaranteed;
+      } else if (loweredTL.isTrivial()) {
+        convention = ParameterConvention::Direct_Unowned;
+      } else {
+        convention = ParameterConvention::Direct_Guaranteed;
+      }
+      SILParameterInfo param(loweredTy.getSwiftRValueType(), convention);
+      inputs.push_back(param);
+      break;
+    }
+    case CaptureKind::Box: {
+      // Lvalues are captured as a box that owns the captured value.
+      auto boxTy = Types.getInterfaceBoxTypeForCapture(
+          VD, loweredTy.getSwiftRValueType(),
+          /*mutable*/ true);
+      auto convention = ParameterConvention::Direct_Guaranteed;
+      auto param = SILParameterInfo(boxTy, convention);
+      inputs.push_back(param);
+      break;
+    }
+    case CaptureKind::StorageAddress: {
+      // Non-escaping lvalues are captured as the address of the value.
+      SILType ty = loweredTy.getAddressType();
+      auto param =
+          SILParameterInfo(ty.getSwiftRValueType(),
+                           ParameterConvention::Indirect_InoutAliasable);
+      inputs.push_back(param);
+      break;
+    }
+    }
+  }
+}
+
 /// Create the appropriate SIL function type for the given formal type
 /// and conventions.
 ///
@@ -814,36 +927,14 @@
   }
 
   // Lower the result type.
-
   AbstractionPattern origResultType = origType.getFunctionResultType();
   CanType substFormalResultType = substFnInterfaceType.getResult();
 
   // If we have a foreign error convention, restore the original result type.
-  if (foreignInfo.Error) {
-    auto &foreignError = *foreignInfo.Error;
-    switch (foreignError.getKind()) {
-    // These conventions replace the result type.
-    case ForeignErrorConvention::ZeroResult:
-    case ForeignErrorConvention::NonZeroResult:
-      assert(substFormalResultType->isVoid());
-      substFormalResultType = foreignError.getResultType();
-      origResultType = AbstractionPattern(genericSig, substFormalResultType);
-      break;
-
-    // These conventions wrap the result type in a level of optionality.
-    case ForeignErrorConvention::NilResult:
-      assert(!substFormalResultType->getAnyOptionalObjectType());
-      substFormalResultType =
-        OptionalType::get(substFormalResultType)->getCanonicalType();
-      origResultType =
-        AbstractionPattern::getOptional(origResultType, OTK_Optional);
-      break;
-
-    // These conventions don't require changes to the formal error type.
-    case ForeignErrorConvention::ZeroPreservedResult:
-    case ForeignErrorConvention::NonNilError:
-      break;
-    }
+  if (auto convention = foreignInfo.Error) {
+    std::tie(origResultType, substFormalResultType) =
+        updateResultTypeForForeignError(*convention, genericSig, origResultType,
+                                        substFormalResultType);
   }
 
   // Destructure the result tuple type.
@@ -863,96 +954,19 @@
   }
   
   // Lower the capture context parameters, if any.
-  // But note that default arg generators can't capture anything right now,
-  // and if we ever add that ability, it will be a different capture list
+  //
+  // *NOTE* Currently default arg generators can not capture anything.
+  // If we ever add that ability, it will be a different capture list
   // from the function to which the argument is attached.
-  if (constant && !constant->isDefaultArgGenerator())
-  if (auto function = constant->getAnyFunctionRef()) {
-    // NB: The generic signature may be elided from the lowered function type
-    // if the function is in a fully-specialized context, but we still need to
-    // canonicalize references to the generic parameters that may appear in
-    // non-canonical types in that context. We need the original generic
-    // signature from the AST for that.
-    auto origGenericSig
-      = function->getGenericSignature();
-
-    auto &Types = M.Types;
-    auto loweredCaptures = Types.getLoweredLocalCaptures(*function);
-    
-    for (auto capture : loweredCaptures.getCaptures()) {
-      if (capture.isDynamicSelfMetadata()) {
-        ParameterConvention convention = ParameterConvention::Direct_Unowned;
-        auto dynamicSelfInterfaceType =
-            loweredCaptures.getDynamicSelfType()->mapTypeOutOfContext();
-        
-        auto selfMetatype = MetatypeType::get(
-            dynamicSelfInterfaceType,
-            MetatypeRepresentation::Thick);
-        
-        auto canSelfMetatype =
-          selfMetatype->getCanonicalType(origGenericSig);
-        SILParameterInfo param(canSelfMetatype, convention);
-        inputs.push_back(param);
-
-        continue;
-      }
-
-      auto *VD = capture.getDecl();
-      auto type = VD->getInterfaceType();
-      auto canType = type->getCanonicalType(origGenericSig);
-
-      auto &loweredTL = Types.getTypeLowering(
-                              AbstractionPattern(genericSig, canType), canType);
-      auto loweredTy = loweredTL.getLoweredType();
-      switch (Types.getDeclCaptureKind(capture)) {
-      case CaptureKind::None:
-        break;
-      case CaptureKind::Constant: {
-        // Constants are captured by value.
-        ParameterConvention convention;
-        if (loweredTL.isAddressOnly()) {
-          convention = M.getOptions().EnableGuaranteedClosureContexts
-            ? ParameterConvention::Indirect_In_Guaranteed
-            : ParameterConvention::Indirect_In;
-        } else if (loweredTL.isTrivial()) {
-          convention = ParameterConvention::Direct_Unowned;
-        } else {
-          convention = M.getOptions().EnableGuaranteedClosureContexts
-            ? ParameterConvention::Direct_Guaranteed
-            : ParameterConvention::Direct_Owned;
-        }
-        SILParameterInfo param(loweredTy.getSwiftRValueType(), convention);
-        inputs.push_back(param);
-        break;
-      }
-      case CaptureKind::Box: {
-        // Lvalues are captured as a box that owns the captured value.
-        auto boxTy = Types.getInterfaceBoxTypeForCapture(VD,
-                                                 loweredTy.getSwiftRValueType(),
-                                                 /*mutable*/ true);
-        auto convention = M.getOptions().EnableGuaranteedClosureContexts
-          ? ParameterConvention::Direct_Guaranteed
-          : ParameterConvention::Direct_Owned;
-        auto param = SILParameterInfo(boxTy, convention);
-        inputs.push_back(param);
-        break;
-      }
-      case CaptureKind::StorageAddress: {
-        // Non-escaping lvalues are captured as the address of the value.
-        SILType ty = loweredTy.getAddressType();
-        auto param = SILParameterInfo(ty.getSwiftRValueType(),
-                                  ParameterConvention::Indirect_InoutAliasable);
-        inputs.push_back(param);
-        break;
-      }
-      }
+  if (constant && !constant->isDefaultArgGenerator()) {
+    if (auto function = constant->getAnyFunctionRef()) {
+      lowerCaptureContextParameters(M, *function, genericSig, inputs);
     }
   }
   
   auto calleeConvention = ParameterConvention::Direct_Unowned;
   if (extInfo.hasContext())
-    calleeConvention =
-        conventions.getCallee(M.getOptions().EnableGuaranteedClosureContexts);
+    calleeConvention = conventions.getCallee();
 
   bool pseudogeneric = (constant ? isPseudogeneric(*constant) : false);
 
@@ -991,7 +1005,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");
   }
 
@@ -1024,27 +1038,39 @@
 
 namespace {
 
-/// The default Swift conventions.
-struct DefaultConventions : Conventions {
+enum class NormalParameterConvention { Owned, Guaranteed };
 
-  DefaultConventions()
-    : Conventions(ConventionsKind::Default) {}
+/// The default Swift conventions.
+class DefaultConventions : public Conventions {
+  NormalParameterConvention normalParameterConvention;
+
+public:
+  DefaultConventions(NormalParameterConvention normalParameterConvention)
+      : Conventions(ConventionsKind::Default),
+        normalParameterConvention(normalParameterConvention) {}
+
+  bool isNormalParameterConventionGuaranteed() const {
+    return normalParameterConvention == NormalParameterConvention::Guaranteed;
+  }
 
   ParameterConvention getIndirectParameter(unsigned index,
                             const AbstractionPattern &type,
                             const TypeLowering &substTL) const override {
+    if (isNormalParameterConventionGuaranteed()) {
+      return ParameterConvention::Indirect_In_Guaranteed;
+    }
     return ParameterConvention::Indirect_In;
   }
 
   ParameterConvention getDirectParameter(unsigned index,
                             const AbstractionPattern &type,
                             const TypeLowering &substTL) const override {
+    if (isNormalParameterConventionGuaranteed())
+      return ParameterConvention::Direct_Guaranteed;
     return ParameterConvention::Direct_Owned;
   }
 
-  ParameterConvention getCallee(bool useGuaranteedContext) const override {
-    if (useGuaranteedContext)
-      return ParameterConvention::Direct_Guaranteed;
+  ParameterConvention getCallee() const override {
     return DefaultThickCalleeConvention;
   }
 
@@ -1068,12 +1094,22 @@
 };
 
 /// The default conventions for Swift initializing constructors.
+///
+/// Initializing constructors take all parameters (including) self at +1. This
+/// is because:
+///
+/// 1. We are likely to be initializing fields of self implying that the
+///    parameters are likely to be forwarded into memory without further
+///    copies.
+/// 2. Initializers must take 'self' at +1, since they will return it back
+///    at +1, and may chain onto Objective-C initializers that replace the
+///    instance.
 struct DefaultInitializerConventions : DefaultConventions {
-  using DefaultConventions::DefaultConventions;
+  DefaultInitializerConventions()
+      : DefaultConventions(NormalParameterConvention::Owned) {}
 
-  /// Initializers must take 'self' at +1, since they will return it back
-  /// at +1, and may chain onto Objective-C initializers that replace the
-  /// instance.
+  /// Initializers must take 'self' at +1, since they will return it back at +1,
+  /// and may chain onto Objective-C initializers that replace the instance.
   ParameterConvention
   getDirectSelfParameter(const AbstractionPattern &type) const override {
     return ParameterConvention::Direct_Owned;
@@ -1085,6 +1121,34 @@
   }
 };
 
+/// The convention used for allocating inits. Allocating inits take their normal
+/// parameters at +1 and do not have a self parameter.
+struct DefaultAllocatorConventions : DefaultConventions {
+  DefaultAllocatorConventions()
+      : DefaultConventions(NormalParameterConvention::Owned) {}
+
+  ParameterConvention
+  getDirectSelfParameter(const AbstractionPattern &type) const override {
+    llvm_unreachable("Allocating inits do not have self parameters");
+  }
+
+  ParameterConvention
+  getIndirectSelfParameter(const AbstractionPattern &type) const override {
+    llvm_unreachable("Allocating inits do not have self parameters");
+  }
+};
+
+/// The default conventions for Swift setter acccessors.
+///
+/// These take self at +0, but all other parameters at +1. This is because we
+/// assume that setter parameters are likely to be values to be forwarded into
+/// memory. Thus by passing in the +1 value, we avoid a potential copy in that
+/// case.
+struct DefaultSetterConventions : DefaultConventions {
+  DefaultSetterConventions()
+      : DefaultConventions(NormalParameterConvention::Owned) {}
+};
+
 /// The default conventions for ObjC blocks.
 struct DefaultBlockConventions : Conventions {
   DefaultBlockConventions() : Conventions(ConventionsKind::DefaultBlock) {}
@@ -1101,7 +1165,7 @@
     return ParameterConvention::Direct_Unowned;
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     return ParameterConvention::Direct_Unowned;
   }
 
@@ -1133,6 +1197,14 @@
                                        AnyFunctionType::ExtInfo extInfo,
                                        Optional<SILDeclRef> constant);
 
+/// If EnableGuaranteedNormalArguments is set, return a default convention that
+/// uses guaranteed.
+static DefaultConventions getNormalArgumentConvention(SILModule &M) {
+  if (M.getOptions().EnableGuaranteedNormalArguments)
+    return DefaultConventions(NormalParameterConvention::Guaranteed);
+  return DefaultConventions(NormalParameterConvention::Owned);
+}
+
 static CanSILFunctionType getNativeSILFunctionType(
     SILModule &M, AbstractionPattern origType,
     CanAnyFunctionType substInterfaceType, AnyFunctionType::ExtInfo extInfo,
@@ -1156,9 +1228,19 @@
       return getSILFunctionType(M, origType, substInterfaceType, extInfo,
                                 DefaultInitializerConventions(), ForeignInfo(),
                                 constant, witnessMethodConformance);
-
-    case SILDeclRef::Kind::Func:
     case SILDeclRef::Kind::Allocator:
+      return getSILFunctionType(M, origType, substInterfaceType, extInfo,
+                                DefaultAllocatorConventions(), ForeignInfo(),
+                                constant, witnessMethodConformance);
+    case SILDeclRef::Kind::Func:
+      // If we have a setter, use the special setter convention. This ensures
+      // that we take normal parameters at +1.
+      if (constant && constant->isSetter()) {
+        return getSILFunctionType(M, origType, substInterfaceType, extInfo,
+                                  DefaultSetterConventions(), ForeignInfo(),
+                                  constant, witnessMethodConformance);
+      }
+      LLVM_FALLTHROUGH;
     case SILDeclRef::Kind::Destroyer:
     case SILDeclRef::Kind::GlobalAccessor:
     case SILDeclRef::Kind::GlobalGetter:
@@ -1168,8 +1250,8 @@
     case SILDeclRef::Kind::IVarDestroyer:
     case SILDeclRef::Kind::EnumElement:
       return getSILFunctionType(M, origType, substInterfaceType, extInfo,
-                                DefaultConventions(), ForeignInfo(), constant,
-                                witnessMethodConformance);
+                                getNormalArgumentConvention(M), ForeignInfo(),
+                                constant, witnessMethodConformance);
     case SILDeclRef::Kind::Deallocator:
       return getSILFunctionType(M, origType, substInterfaceType, extInfo,
                                 DeallocatorConventions(), ForeignInfo(),
@@ -1273,7 +1355,7 @@
     return getDirectCParameterConvention(Method->param_begin()[index]);
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // Always thin.
     return ParameterConvention::Direct_Unowned;
   }
@@ -1424,7 +1506,7 @@
     return getDirectCParameterConvention(getParamType(index));
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // FIXME: blocks should be Direct_Guaranteed.
     return ParameterConvention::Direct_Unowned;
   }
@@ -1719,7 +1801,7 @@
     return ParameterConvention::Direct_Unowned;
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // Always thin.
     return ParameterConvention::Direct_Unowned;
   }
@@ -2621,3 +2703,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..ec236c0 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,18 @@
   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);
+  // Make sure we are not performing ABI-incompatible conversions.
+  CanSILFunctionType opTI =
+      CFI->getOperand()->getType().castTo<SILFunctionType>();
+  (void)opTI;
+  CanSILFunctionType resTI =
+      CFI->getOperand()->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/ManagedValue.cpp b/lib/SILGen/ManagedValue.cpp
index c578420..02491e8 100644
--- a/lib/SILGen/ManagedValue.cpp
+++ b/lib/SILGen/ManagedValue.cpp
@@ -110,10 +110,15 @@
 
 void ManagedValue::forwardInto(SILGenFunction &SGF, SILLocation loc,
                                SILValue address) {
+  if (!hasCleanup() && getOwnershipKind() != ValueOwnershipKind::Trivial)
+    return copyUnmanaged(SGF, loc).forwardInto(SGF, loc, address);
+
   if (hasCleanup())
     forwardCleanup(SGF);
+
   auto &addrTL = SGF.getTypeLowering(address->getType());
-  SGF.emitSemanticStore(loc, getValue(), address, addrTL, IsInitialization);
+  SGF.emitSemanticStore(loc, getValue(), address,
+                        addrTL, IsInitialization);
 }
 
 void ManagedValue::assignInto(SILGenFunction &SGF, SILLocation loc,
@@ -195,3 +200,13 @@
     os << "<null>\n";
   }
 }
+
+ManagedValue ManagedValue::ensurePlusOne(SILGenFunction &SGF,
+                                         SILLocation loc) const {
+  // guaranteed-normal-args-todo: We only copy here when guaranteed normal args
+  // are explicitly enabled. Otherwise, this always just returns self.
+  if (SGF.getOptions().EnableGuaranteedNormalArguments && !hasCleanup()) {
+    return copy(SGF, loc);
+  }
+  return *this;
+}
diff --git a/lib/SILGen/ManagedValue.h b/lib/SILGen/ManagedValue.h
index 30e1735..20ecc8c 100644
--- a/lib/SILGen/ManagedValue.h
+++ b/lib/SILGen/ManagedValue.h
@@ -271,6 +271,10 @@
     return isLValue() ? *this : ManagedValue::forUnmanaged(getValue());
   }
 
+  /// If this managed value is a plus one value, return *this. If this is a plus
+  /// zero value, return a copy instead.
+  ManagedValue ensurePlusOne(SILGenFunction &SGF, SILLocation loc) const;
+
   /// Given a scalar value, materialize it into memory with the
   /// exact same level of cleanup it had before.
   ManagedValue materialize(SILGenFunction &SGF, SILLocation loc) const;
diff --git a/lib/SILGen/RValue.cpp b/lib/SILGen/RValue.cpp
index cf01dec..bc39d12 100644
--- a/lib/SILGen/RValue.cpp
+++ b/lib/SILGen/RValue.cpp
@@ -698,6 +698,12 @@
   return RValue(SGF, std::move(copiedValues), type, elementsToBeAdded);
 }
 
+RValue RValue::ensurePlusOne(SILGenFunction &SGF, SILLocation loc) && {
+  if (SGF.getOptions().EnableGuaranteedNormalArguments && isPlusZero(SGF))
+    return copy(SGF, loc);
+  return std::move(*this);
+}
+
 RValue RValue::borrow(SILGenFunction &SGF, SILLocation loc) const & {
   assert((isComplete() || isInSpecialState()) &&
          "can't borrow incomplete rvalue");
diff --git a/lib/SILGen/RValue.h b/lib/SILGen/RValue.h
index a8b41d9..7028c82 100644
--- a/lib/SILGen/RValue.h
+++ b/lib/SILGen/RValue.h
@@ -348,6 +348,10 @@
   /// Emit an equivalent value with independent ownership.
   RValue copy(SILGenFunction &SGF, SILLocation loc) const &;
 
+  /// If this RValue is a +0 value, copy the RValue and return. Otherwise,
+  /// return std::move(*this);
+  RValue ensurePlusOne(SILGenFunction &SGF, SILLocation loc) &&;
+
   /// Borrow all subvalues of the rvalue.
   RValue borrow(SILGenFunction &SGF, SILLocation loc) const &;
 
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index d022b32..7bf47ae 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -418,7 +418,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 +551,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: {
@@ -4086,9 +4097,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);
 
@@ -4159,13 +4168,13 @@
                               firstLevelResult.foreignSelf, uncurriedArgs,
                               uncurriedLoc, formalApplyType);
 
-  // Emit the uncurried call.
+  // If we have a late emitter, just delegate to that emitter and return.
   if (specializedEmitter.isLateEmitter()) {
     auto emitter = specializedEmitter.getLateEmitter();
+    ManagedValue mv = emitter(SGF, *uncurriedLoc, callee.getSubstitutions(),
+                              uncurriedArgs, uncurriedContext);
     firstLevelResult.value =
-        RValue(SGF, *uncurriedLoc, formalApplyType.getResult(),
-               emitter(SGF, uncurriedLoc.getValue(), callee.getSubstitutions(),
-                       uncurriedArgs, uncurriedContext));
+        RValue(SGF, *uncurriedLoc, formalApplyType.getResult(), mv);
     return firstLevelResult;
   }
 
@@ -4806,7 +4815,6 @@
   // base isn't a temporary.  We aren't allowed to pass aliased
   // memory to 'in', and we have pass at +1.
   case ParameterConvention::Indirect_In:
-  case ParameterConvention::Indirect_In_Constant:
   case ParameterConvention::Indirect_In_Guaranteed:
     // TODO: We shouldn't be able to get an lvalue here, but the AST
     // sometimes produces an inout base for non-mutating accessors.
@@ -4820,6 +4828,10 @@
   case ParameterConvention::Direct_Unowned:
   case ParameterConvention::Direct_Guaranteed:
     return true;
+
+  // Should not show up here.
+  case ParameterConvention::Indirect_In_Constant:
+    break;
   }
   llvm_unreachable("bad convention");
 }
@@ -5275,9 +5287,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 164b3ec..09a8a16 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -313,7 +313,6 @@
     return ManagedValue::forLValue(value);
 
   case ParameterConvention::Indirect_In_Guaranteed:
-  case ParameterConvention::Indirect_In_Constant:
     if (valueTL.isLoadable()) {
       return SGF.emitLoad(loc, value, valueTL, SGFContext(), IsNotTake);
     } else {
@@ -327,8 +326,9 @@
       return SGF.emitManagedRValueWithCleanup(value, valueTL);
     }
 
+  case ParameterConvention::Indirect_In_Constant:
   case ParameterConvention::Indirect_InoutAliasable:
-    llvm_unreachable("unexpected inout_aliasable argument");
+    llvm_unreachable("unexpected convention");
   }
   llvm_unreachable("bad convention");
 }
@@ -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);
 }
@@ -1632,15 +1631,17 @@
           param = ManagedValue::forLValue(paramValue);
           break;
         case ParameterConvention::Indirect_In:
-        case ParameterConvention::Indirect_In_Constant:
           param = emitManagedRValueWithCleanup(paramValue);
           break;
-        case ParameterConvention::Indirect_In_Guaranteed:
+        case ParameterConvention::Indirect_In_Guaranteed: {
           auto tmp = emitTemporaryAllocation(fd, paramValue->getType());
           B.createCopyAddr(fd, paramValue, tmp, IsNotTake, IsInitialization);
           param = emitManagedRValueWithCleanup(tmp);
           break;
         }
+        case ParameterConvention::Indirect_In_Constant:
+          llvm_unreachable("unsupported convention");
+        }
 
         maybeAddForeignErrorArg();
 
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index 0512eb1..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) {
@@ -731,6 +715,78 @@
   createStoreBorrow(loc, value, address);
 }
 
+ManagedValue SILGenBuilder::createBridgeObjectToRef(SILLocation loc,
+                                                    ManagedValue mv,
+                                                    SILType destType) {
+  CleanupCloner cloner(*this, mv);
+  SILValue result = createBridgeObjectToRef(loc, mv.forward(SGF), destType);
+  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) {
+  llvm::SmallVector<SILValue, 8> newArgs;
+  transform(args, std::back_inserter(newArgs),
+            [&](ManagedValue mv) -> SILValue { return mv.forward(SGF); });
+  return createBranch(loc, targetBlock, newArgs);
+}
+
+ReturnInst *SILGenBuilder::createReturn(SILLocation loc,
+                                        ManagedValue returnValue) {
+  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 120387f..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);
@@ -323,6 +330,17 @@
   using SILBuilder::createValueMetatype;
   ManagedValue createValueMetatype(SILLocation loc, SILType metatype,
                                    ManagedValue base);
+
+  using SILBuilder::createBridgeObjectToRef;
+  ManagedValue createBridgeObjectToRef(SILLocation loc, ManagedValue mv,
+                                       SILType destType);
+
+  using SILBuilder::createBranch;
+  BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
+                           ArrayRef<ManagedValue> Args);
+
+  using SILBuilder::createReturn;
+  ReturnInst *createReturn(SILLocation Loc, ManagedValue ReturnValue);
 };
 
 class SwitchCaseFullExpr;
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index 8eac6d0..2c9bdf8 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -718,11 +718,10 @@
     SILValue result = SILUndef::get(destType, SGF.SGM.M);
     return ManagedValue::forUnmanaged(result);
   }
-  
-  SILValue result = SGF.B.createBridgeObjectToRef(loc, args[0].forward(SGF),
-                                                  destType);
-  return SGF.emitManagedRValueWithCleanup(result);
+
+  return SGF.B.createBridgeObjectToRef(loc, args[0], destType);
 }
+
 static ManagedValue emitBuiltinCastBitPatternFromBridgeObject(
                                                   SILGenFunction &SGF,
                                                   SILLocation loc,
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/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/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 978debb..6620749 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -1633,8 +1633,7 @@
   /// Used for emitting SILArguments of bare functions, such as thunks and
   /// open-coded materializeForSet.
   void collectThunkParams(SILLocation loc,
-                          SmallVectorImpl<ManagedValue> &params,
-                          bool allowPlusZero);
+                          SmallVectorImpl<ManagedValue> &params);
 
   /// Build the type of a function transformation thunk.
   CanSILFunctionType buildThunkType(CanSILFunctionType &sourceType,
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 859abba..d520fb9 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -3358,7 +3358,7 @@
       std::move(component.asPhysical()).offset(*this, loc, destAddr,
                                                AccessKind::Write);
 
-    auto value = std::move(src).getAsRValue(*this);
+    auto value = std::move(src).getAsRValue(*this).ensurePlusOne(*this, loc);
     std::move(value).assignInto(*this, loc, finalDestAddr.getValue());
   } else {
     std::move(component.asLogical()).set(*this, loc, std::move(src), destAddr);
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index ff8f2c2..cba7805 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -524,7 +524,7 @@
   SGF.F.setBare(IsBare);
 
   SmallVector<ManagedValue, 4> params;
-  SGF.collectThunkParams(loc, params, /*allowPlusZero*/ true);
+  SGF.collectThunkParams(loc, params);
 
   ManagedValue self = params.back();
   SILValue resultBuffer = params[0].getUnmanagedValue();
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 1263fff..d503baa 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -341,6 +341,9 @@
                                     ManagedValue addr,
                                     const TypeLowering &addrTL) {
   // SEMANTIC ARC TODO: When the verifier is finished, revisit this.
+  if (!addr.hasCleanup())
+    return SGF.B.createLoadBorrow(loc, addr);
+
   auto loadedValue = addrTL.emitLoad(SGF.B, loc, addr.forward(SGF),
                                      LoadOwnershipQualifier::Take);
   return SGF.emitManagedRValueWithCleanup(loadedValue, addrTL);
@@ -520,6 +523,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
@@ -613,47 +625,29 @@
 static void explodeTuple(SILGenFunction &SGF, SILLocation loc,
                          ManagedValue managedTuple,
                          SmallVectorImpl<ManagedValue> &out) {
+  // If the tuple is empty, there's nothing to do.
+  if (managedTuple.getType().castTo<TupleType>()->getNumElements() == 0)
+    return;
 
-  assert(managedTuple.getOwnershipKind() == ValueOwnershipKind::Trivial
-         || managedTuple.hasCleanup());
+  SmallVector<SILValue, 16> elements;
+  bool isPlusOne = managedTuple.hasCleanup();
 
-  // For non-address types, borrow the tuple before extracting and copying its
-  // elements. Creating a scope here ensures that the end_borrow is inserted
-  // correctly and prevents any other cleanup activity from taking meanwhile. We
-  // allow the incoming managedTuple to be destroyed later in its original
-  // scope.
-  //
-  // SEMANTIC SIL TODO: Once we support a SIL "destructure" instruction, we can
-  // remove this borrow scope and all element copies. Instead directly forward
-  // managedTuple into its destructure.
-  Scope destructureScope(SGF, loc);
-  ManagedValue tuple =
-      managedTuple.getType().isAddress()
-          ? ManagedValue::forUnmanaged(managedTuple.forward(SGF))
-          : managedTuple.borrow(SGF, loc);
-
-  auto tupleSILType = tuple.getType();
-  auto tupleType = tupleSILType.castTo<TupleType>();
-
-  llvm::SmallVector<ManagedValue, 16> elements;
-  elements.reserve(tupleType->getNumElements());
-
-  for (auto index : indices(tupleType.getElementTypes())) {
-    // We're starting with a SIL-lowered tuple type, so the elements
-    // must also all be SIL-lowered.
-    SILType eltType = tupleSILType.getTupleElementType(index);
-
-    if (tupleSILType.isAddress()) {
-      elements.push_back(
-          SGF.B.createTupleElementAddr(loc, tuple, index, eltType));
-    } else {
-      ManagedValue extract =
-          SGF.B.createTupleExtract(loc, tuple, index, eltType);
-      elements.push_back(extract.copy(SGF, loc));
-    }
+  if (managedTuple.getType().isAddress()) {
+    SGF.B.emitShallowDestructureAddressOperation(loc, managedTuple.forward(SGF),
+                                                 elements);
+  } else {
+    SGF.B.emitShallowDestructureValueOperation(loc, managedTuple.forward(SGF),
+                                               elements);
   }
-  out.resize(elements.size());
-  destructureScope.popPreservingValues(elements, out);
+
+  for (auto element : elements) {
+    if (!isPlusOne)
+      out.push_back(ManagedValue::forUnmanaged(element));
+    else if (element->getType().isAddress())
+      out.push_back(SGF.emitManagedBufferWithCleanup(element));
+    else
+      out.push_back(SGF.emitManagedRValueWithCleanup(element));
+  }
 }
 
 /// Apply this transformation to all the elements of a tuple value,
@@ -770,26 +764,14 @@
 static ManagedValue manageParam(SILGenFunction &SGF,
                                 SILLocation loc,
                                 SILValue paramValue,
-                                SILParameterInfo info,
-                                bool allowPlusZero) {
+                                SILParameterInfo info) {
   switch (info.getConvention()) {
   case ParameterConvention::Indirect_In_Guaranteed:
-    if (SGF.silConv.useLoweredAddresses()) {
-      // FIXME: Avoid a behavior change while guaranteed self is disabled by
-      // default.
-      if (allowPlusZero) {
-        return ManagedValue::forUnmanaged(paramValue);
-      } else {
-        auto copy = SGF.emitTemporaryAllocation(loc, paramValue->getType());
-        SGF.B.createCopyAddr(loc, paramValue, copy, IsNotTake, IsInitialization);
-        return SGF.emitManagedBufferWithCleanup(copy);
-      }
-    }
+    if (SGF.silConv.useLoweredAddresses())
+      return ManagedValue::forUnmanaged(paramValue);
     LLVM_FALLTHROUGH;
   case ParameterConvention::Direct_Guaranteed:
-    if (allowPlusZero)
-      return SGF.emitManagedBeginBorrow(loc, paramValue);
-    LLVM_FALLTHROUGH;
+    return SGF.emitManagedBeginBorrow(loc, paramValue);
   // Unowned parameters are only guaranteed at the instant of the call, so we
   // must retain them even if we're in a context that can accept a +0 value.
   case ParameterConvention::Direct_Unowned:
@@ -800,7 +782,6 @@
     return SGF.emitManagedRValueWithCleanup(paramValue);
 
   case ParameterConvention::Indirect_In:
-  case ParameterConvention::Indirect_In_Constant:
     if (SGF.silConv.useLoweredAddresses())
       return SGF.emitManagedBufferWithCleanup(paramValue);
     return SGF.emitManagedRValueWithCleanup(paramValue);
@@ -808,13 +789,14 @@
   case ParameterConvention::Indirect_Inout:
   case ParameterConvention::Indirect_InoutAliasable:
     return ManagedValue::forLValue(paramValue);
+  case ParameterConvention::Indirect_In_Constant:
+    break;
   }
   llvm_unreachable("bad parameter convention");
 }
 
 void SILGenFunction::collectThunkParams(SILLocation loc,
-                                        SmallVectorImpl<ManagedValue> &params,
-                                        bool allowPlusZero) {
+                                        SmallVectorImpl<ManagedValue> &params) {
   // Add the indirect results.
   for (auto resultTy : F.getConventions().getIndirectSILResultTypes()) {
     auto paramTy = F.mapTypeIntoContext(resultTy);
@@ -827,7 +809,7 @@
   for (auto param : paramTypes) {
     auto paramTy = F.mapTypeIntoContext(F.getConventions().getSILType(param));
     auto paramValue = F.begin()->createFunctionArgument(paramTy);
-    auto paramMV = manageParam(*this, loc, paramValue, param, allowPlusZero);
+    auto paramMV = manageParam(*this, loc, paramValue, param);
     params.push_back(paramMV);
   }
 }
@@ -1343,6 +1325,18 @@
                          SILParameterInfo result) {
       // Easy case: we want to pass exactly this value.
       if (input.getType() == SGF.getSILType(result)) {
+        switch (result.getConvention()) {
+        case ParameterConvention::Direct_Owned:
+        case ParameterConvention::Indirect_In:
+          if (!input.hasCleanup() &&
+              input.getOwnershipKind() != ValueOwnershipKind::Trivial)
+            input = input.copyUnmanaged(SGF, Loc);
+          break;
+
+        default:
+          break;
+        }
+
         Outputs.push_back(input);
         return;
       }
@@ -1368,8 +1362,7 @@
         llvm::errs() << "output type " << SGF.getSILType(result) << "\n";
         abort();
       }
-      case ParameterConvention::Indirect_In:
-      case ParameterConvention::Indirect_In_Constant: {
+      case ParameterConvention::Indirect_In: {
         if (SGF.silConv.useLoweredAddresses()) {
           translateIndirect(inputOrigType, inputSubstType, outputOrigType,
                             outputSubstType, input, SGF.getSILType(result));
@@ -1391,10 +1384,11 @@
         assert(Outputs.back().getType() == SGF.getSILType(result));
         return;
       }
-      case ParameterConvention::Indirect_InoutAliasable: {
+      case ParameterConvention::Indirect_InoutAliasable:
         llvm_unreachable("abstraction difference in aliasable argument not "
                          "allowed");
-      }
+      case ParameterConvention::Indirect_In_Constant:
+        llvm_unreachable("in_constant convention not allowed in SILGen");
       }
 
       llvm_unreachable("Covered switch isn't covered?!");
@@ -2585,9 +2579,7 @@
   FullExpr scope(SGF.Cleanups, CleanupLocation::get(loc));
 
   SmallVector<ManagedValue, 8> params;
-  // TODO: Could accept +0 arguments here when forwardFunctionArguments/
-  // emitApply can.
-  SGF.collectThunkParams(loc, params, /*allowPlusZero*/ false);
+  SGF.collectThunkParams(loc, params);
 
   ManagedValue fnValue = params.pop_back_val();
   auto fnType = fnValue.getType().castTo<SILFunctionType>();
@@ -2820,9 +2812,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());
@@ -2934,7 +2924,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,
@@ -3166,7 +3156,7 @@
   auto thunkTy = F.getLoweredFunctionType();
 
   SmallVector<ManagedValue, 8> thunkArgs;
-  collectThunkParams(loc, thunkArgs, /*allowPlusZero*/ true);
+  collectThunkParams(loc, thunkArgs);
 
   SmallVector<ManagedValue, 8> substArgs;
 
@@ -3315,9 +3305,7 @@
   auto thunkTy = F.getLoweredFunctionType();
 
   SmallVector<ManagedValue, 8> origParams;
-  // TODO: Should be able to accept +0 values here, once
-  // forwardFunctionArguments/emitApply are able to.
-  collectThunkParams(loc, origParams, /*allowPlusZero*/ false);
+  collectThunkParams(loc, origParams);
 
   // Handle special abstraction differences in "self".
   // If the witness is a free function, drop it completely.
@@ -3355,31 +3343,6 @@
     witnessFTy = origWitnessFTy->substGenericArgs(SGM.M, witnessSubs);
 
   SmallVector<ManagedValue, 8> witnessParams;
-
-  if (!isFree) {
-    // If the requirement has a self parameter passed as an indirect +0 value,
-    // and the witness takes it as a non-inout value, we must load and retain
-    // the self pointer coming in.  This happens when class witnesses implement
-    // non-mutating protocol requirements.
-    auto reqConvention = thunkTy->getSelfParameter().getConvention();
-    auto witnessConvention = witnessFTy->getSelfParameter().getConvention();
-    
-    bool inoutDifference;
-    
-    inoutDifference = reqConvention == ParameterConvention::Indirect_Inout &&
-                    witnessConvention != ParameterConvention::Indirect_Inout;
-
-    if (inoutDifference) {
-      // If there is an inout difference in self, load the inout self parameter.
-      ManagedValue &selfParam = origParams.back();
-      SILValue selfAddr = selfParam.getUnmanagedValue();
-      selfParam = emitLoad(loc, selfAddr,
-                           getTypeLowering(selfType),
-                           SGFContext(),
-                           IsNotTake);
-    }
-  }
-
   AbstractionPattern witnessOrigTy(witnessInfo.LoweredType);
   TranslateArguments(*this, loc,
                      origParams, witnessParams,
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 025443a..ca307e3 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -114,10 +114,12 @@
 
     case ParameterConvention::Direct_Owned:
     case ParameterConvention::Indirect_In:
-    case ParameterConvention::Indirect_In_Constant:
       // An owned or 'in' parameter is passed in at +1. We can claim ownership
       // of the parameter and clean it up when it goes out of scope.
       return SGF.emitManagedRValueWithCleanup(arg);
+
+    case ParameterConvention::Indirect_In_Constant:
+      break;
     }
     llvm_unreachable("bad parameter convention");
   }
@@ -390,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
@@ -399,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;
     }
@@ -432,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 82953ae..3b836a6 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -388,7 +388,8 @@
   } else {
     // SILValue return.
     FullExpr scope(Cleanups, CleanupLocation(ret));
-    emitRValue(ret).forwardAll(*this, directResults);
+    RValue RV = emitRValue(ret).ensurePlusOne(*this, CleanupLocation(ret));
+    std::move(RV).forwardAll(*this, directResults);
   }
   Cleanups.emitBranchAndCleanups(ReturnDest, branchLoc, directResults);
 }
@@ -797,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();
@@ -849,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/Scope.cpp b/lib/SILGen/Scope.cpp
index 420f13e..a4e39b9 100644
--- a/lib/SILGen/Scope.cpp
+++ b/lib/SILGen/Scope.cpp
@@ -119,31 +119,6 @@
   return RValue(SGF, std::move(managedValues), type, numEltsRemaining);
 }
 
-void Scope::popPreservingValues(ArrayRef<ManagedValue> innerValues,
-                                MutableArrayRef<ManagedValue> outerValues) {
-  auto &SGF = cleanups.SGF;
-  assert(innerValues.size() == outerValues.size());
-
-  // Record the cleanup information for each preserved value and deactivate its
-  // cleanup.
-  SmallVector<CleanupCloner, 4> cleanups;
-  cleanups.reserve(innerValues.size());
-  for (auto &mv : innerValues) {
-    cleanups.emplace_back(SGF, mv);
-    mv.forward(SGF);
-  }
-
-  // Pop any unpreserved cleanups.
-  pop();
-
-  // Create a managed value for each preserved value, cloning its cleanup.
-  // Since the CleanupCloner does not remember its SILValue, grab it from the
-  // original, now-deactivated managed value.
-  for (auto index : indices(innerValues)) {
-    outerValues[index] = cleanups[index].clone(innerValues[index].getValue());
-  }
-}
-
 void Scope::popImpl() {
   cleanups.stack.checkIterator(depth);
   cleanups.stack.checkIterator(cleanups.innermostScope);
diff --git a/lib/SILGen/Scope.h b/lib/SILGen/Scope.h
index d836527..89ce3c8 100644
--- a/lib/SILGen/Scope.h
+++ b/lib/SILGen/Scope.h
@@ -65,12 +65,6 @@
   /// plus zero rvalue.
   RValue popPreservingValue(RValue &&rv);
 
-  /// Pop the scope pushing the +1 ManagedValues in `innerValues` through the
-  /// scope. Asserts if any ManagedValue is plus zero. Each cleanup is recreated
-  /// in the outer scope and associated with a managed value in `outerValues`.
-  void popPreservingValues(ArrayRef<ManagedValue> innerValues,
-                           MutableArrayRef<ManagedValue> outerValues);
-
 private:
   /// Internal private implementation of popImpl so we can use it in Scope::pop
   /// and in Scope's destructor.
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/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/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index be39af2..3ecc2b2 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -30,16 +30,6 @@
 
 namespace {
 
-/// Returns true if a given function should always be emitted into client.
-/// Such functions cannot be referenced from outside.
-/// NOTE: Global initializers are never serialized (even if e.g. the
-/// unsafeMutableAddressor is marked as transparent) and thus they cannot be
-/// emitted into clients. They should always be emitted into the defining
-/// module.
-static bool shouldBeAlwaysEmittedIntoClient(SILFunction *F) {
-  return F->isTransparent() && !F->isGlobalInit();
-}
-
 /// Returns true if a function should be SIL serialized or emitted by IRGen.
 static bool shouldBeSerializedOrEmitted(SILFunction *F) {
   // global initializers are always emitted into the defining module and
@@ -48,8 +38,7 @@
     return true;
 
   // public_external functions are never SIL serialized or emitted by IRGen.
-  if (F->isAvailableExternally() && hasPublicVisibility(F->getLinkage()) &&
-      !shouldBeAlwaysEmittedIntoClient(F))
+  if (F->isAvailableExternally() && hasPublicVisibility(F->getLinkage()))
     return false;
 
   // [serialized] functions should always be SIL serialized.
@@ -136,12 +125,7 @@
       return true;
 
     // Functions that may be used externally cannot be removed.
-    // But there is one exception from this rule:
-    // If it is a whole-module compilation and the function is supposed to
-    // always be emitted into client then is does not need to be an anchor as
-    // it cannot be invoked from outside the module.
-    if (isPossiblyUsedExternally(F->getLinkage(), Module->isWholeModule()) &&
-        !shouldBeAlwaysEmittedIntoClient(F))
+    if (isPossiblyUsedExternally(F->getLinkage(), Module->isWholeModule()))
       return true;
 
     // If function is marked as "keep-as-public", don't remove it.
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..4197def 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -1050,8 +1050,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();
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/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/CSApply.cpp b/lib/Sema/CSApply.cpp
index 5c36f94..3a55afb 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -471,9 +471,10 @@
           if (!baseTy->is<ArchetypeType>() && !baseTy->isAnyExistentialType()) {
             auto &tc = cs.getTypeChecker();
             auto conformance =
-              tc.conformsToProtocol(baseTy, proto, cs.DC,
-                                    (ConformanceCheckFlags::InExpression|
-                                         ConformanceCheckFlags::Used));
+              tc.conformsToProtocol(
+                        baseTy, proto, cs.DC,
+                        (ConformanceCheckFlags::InExpression|
+                         ConformanceCheckFlags::Used));
             if (conformance && conformance->isConcrete()) {
               if (auto witness =
                         conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
@@ -2261,8 +2262,6 @@
         tc.conformsToProtocol(conformingType, proto, cs.DC,
                               ConformanceCheckFlags::InExpression);
       assert(conformance && "object literal type conforms to protocol");
-      assert(conformance->getConditionalRequirements().empty() &&
-             "unhandled conditional conformance");
 
       Expr *base = TypeExpr::createImplicitHack(expr->getLoc(), conformingType,
                                                 ctx);
@@ -2713,8 +2712,6 @@
         tc.conformsToProtocol(arrayTy, arrayProto, cs.DC,
                               ConformanceCheckFlags::InExpression);
       assert(conformance && "Type does not conform to protocol?");
-      assert(conformance->getConditionalRequirements().empty() &&
-             "unhandled conditional conformance");
 
       // Call the witness that builds the array literal.
       // FIXME: callWitness() may end up re-doing some work we already did
@@ -2797,9 +2794,6 @@
       if (!conformance)
         return nullptr;
 
-      assert(conformance->getConditionalRequirements().empty() &&
-             "unhandled conditional conformance");
-
       // Call the witness that builds the dictionary literal.
       // FIXME: callWitness() may end up re-doing some work we already did
       // to convert the dictionary literal elements to the (key, value) tuple.
@@ -4295,8 +4289,9 @@
         for (auto indexType : indexTypes) {
           auto conformance =
             cs.TC.conformsToProtocol(indexType.getType(), hashable,
-                                     cs.DC, ConformanceCheckFlags::Used
-                                          |ConformanceCheckFlags::InExpression);
+                                     cs.DC,
+                                     (ConformanceCheckFlags::Used|
+                                      ConformanceCheckFlags::InExpression));
           if (!conformance) {
             cs.TC.diagnose(component.getIndexExpr()->getLoc(),
                            diag::expr_keypath_subscript_index_not_hashable,
@@ -6122,12 +6117,11 @@
       // Find the conformance of the source type to Hashable.
       auto hashable = tc.Context.getProtocol(KnownProtocolKind::Hashable);
       auto conformance =
-        tc.conformsToProtocol(cs.getType(expr), hashable, cs.DC,
-                              (ConformanceCheckFlags::InExpression |
-                               ConformanceCheckFlags::Used));
+        tc.conformsToProtocol(
+                        cs.getType(expr), hashable, cs.DC,
+                        (ConformanceCheckFlags::InExpression |
+                         ConformanceCheckFlags::Used));
       assert(conformance && "must conform to Hashable");
-      assert(conformance->getConditionalRequirements().empty() &&
-             "unhandled conditional conformance");
 
       return cs.cacheType(
           new (tc.Context) AnyHashableErasureExpr(expr, toType, *conformance));
@@ -6556,10 +6550,9 @@
   Optional<ProtocolConformanceRef> builtinConformance;
   if (builtinProtocol &&
       (builtinConformance =
-         tc.conformsToProtocol(type, builtinProtocol, cs.DC,
-                               ConformanceCheckFlags::InExpression))) {
-    assert(builtinConformance->getConditionalRequirements().empty() &&
-           "conditional conformance to builtins not handled");
+         tc.conformsToProtocol(
+                      type, builtinProtocol, cs.DC,
+                      (ConformanceCheckFlags::InExpression)))) {
 
     // Find the builtin argument type we'll use.
     Type argType;
@@ -6710,8 +6703,7 @@
       (builtinConformance =
          tc.conformsToProtocol(type, builtinProtocol, cs.DC,
                                ConformanceCheckFlags::InExpression))) {
-    assert(builtinConformance->getConditionalRequirements().empty() &&
-           "conditional conformance to builtins not handled");
+
     // Find the witness that we'll use to initialize the type via a builtin
     // literal.
     auto witness = findNamedWitnessImpl<AbstractFunctionDecl>(
@@ -7522,9 +7514,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 0d1c0a8..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);
   }
 
@@ -517,8 +519,10 @@
       for (auto proto : literalProtocols) {
         do {
           // If the type conforms to this protocol, we're covered.
-          if (tc.conformsToProtocol(testType, proto, DC,
-                                    ConformanceCheckFlags::InExpression)) {
+          if (tc.conformsToProtocol(
+                      testType, proto, DC,
+                      (ConformanceCheckFlags::InExpression|
+                       ConformanceCheckFlags::SkipConditionalRequirements))) {
             coveredLiteralProtocols.insert(proto);
             break;
           }
@@ -564,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 719c473..3c6a830 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -1431,7 +1431,7 @@
   ValueDecl *member = nullptr;
   for (auto cand : result.UnviableCandidates) {
     if (member == nullptr)
-      member = cand.first;
+      member = cand.first.getDecl();
     sameProblem &= cand.second == firstProblem;
   }
   
@@ -1537,12 +1537,12 @@
     }
         
     case MemberLookupResult::UR_Inaccessible: {
-      auto decl = result.UnviableCandidates[0].first;
+      auto decl = result.UnviableCandidates[0].first.getDecl();
       // FIXME: What if the unviable candidates have different levels of access?
       diagnose(nameLoc, diag::candidate_inaccessible, decl->getBaseName(),
                decl->getFormalAccess());
       for (auto cand : result.UnviableCandidates)
-        diagnose(cand.first, diag::decl_declared_here, memberName);
+        diagnose(cand.first.getDecl(), diag::decl_declared_here, memberName);
         
       return;
     }
@@ -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;
@@ -4810,7 +4831,7 @@
 
   SmallVector<OverloadChoice, 2> choices;
   for (auto &unviable : results.UnviableCandidates)
-    choices.push_back(OverloadChoice(baseType, unviable.first,
+    choices.push_back(OverloadChoice(baseType, unviable.first.getDecl(),
                                      UDE->getFunctionRefKind()));
 
   CalleeCandidateInfo unviableCandidates(baseType, choices, hasTrailingClosure,
@@ -4975,8 +4996,10 @@
 
       TC.diagnose(Candidate, note, first, second,
                   rawFirstType, rawSecondType,
-                  genericSig->gatherGenericParamBindingsText(
-                                 {rawFirstType, rawSecondType}, Substitutions));
+                  TypeChecker::gatherGenericParamBindingsText(
+                    {rawFirstType, rawSecondType},
+                    genericSig->getGenericParams(),
+                    Substitutions));
 
       ParentConditionalConformance::diagnoseConformanceStack(
           TC.Diags, Candidate->getLoc(), parents);
@@ -4992,7 +5015,9 @@
 
   auto result = TC.checkGenericArguments(
       dc, callExpr->getLoc(), fnExpr->getLoc(), AFD->getInterfaceType(),
-      env->getGenericSignature(), substitutionFn,
+      env->getGenericSignature()->getGenericParams(),
+      env->getGenericSignature()->getRequirements(),
+      substitutionFn,
       LookUpConformanceInModule{dc->getParentModule()}, nullptr,
       ConformanceCheckFlags::SuppressDependencyTracking, &genericReqListener);
 
@@ -5078,6 +5103,7 @@
   if (!callExpr->hasTrailingClosure())
     return false;
 
+  auto *DC = CS.DC;
   auto *fnExpr = callExpr->getFn();
   auto *argExpr = callExpr->getArg();
 
@@ -5234,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,
@@ -7356,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;
@@ -7383,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);
@@ -7568,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 efbfd05..7f3e83b 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)
@@ -1329,8 +1330,8 @@
     }
 
     Type resolveTypeReferenceInExpression(TypeRepr *rep) {
-      TypeResolutionOptions options = TR_AllowUnboundGenerics;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+      options |= TypeResolutionFlags::InExpression;
       return CS.TC.resolveType(rep, CS.DC, options);
     }
 
@@ -1553,9 +1554,9 @@
           // open type.
           auto locator = CS.getConstraintLocator(expr);
           for (size_t i = 0, size = specializations.size(); i < size; ++i) {
-            if (tc.validateType(specializations[i], CS.DC,
-                                (TR_InExpression |
-                                 TR_AllowUnboundGenerics)))
+            TypeResolutionOptions options = TypeResolutionFlags::InExpression;
+            options |= TypeResolutionFlags::AllowUnboundGenerics;
+            if (tc.validateType(specializations[i], CS.DC, options))
               return Type();
 
             CS.addConstraint(ConstraintKind::Equal,
@@ -2169,7 +2170,7 @@
           pattern = pattern->getSemanticsProvidingPattern();
           while (auto isp = dyn_cast<IsPattern>(pattern)) {
             if (CS.TC.validateType(isp->getCastTypeLoc(), CS.DC,
-                                   TR_InExpression))
+                                   TypeResolutionFlags::InExpression))
               return false;
 
             if (!isp->hasSubPattern()) {
@@ -2189,7 +2190,7 @@
           Type exnType = CS.TC.getExceptionType(CS.DC, clause->getCatchLoc());
           if (!exnType ||
               CS.TC.coercePatternToType(pattern, CS.DC, exnType,
-                                        TR_InExpression)) {
+                                        TypeResolutionFlags::InExpression)) {
             return false;
           }
 
@@ -2500,8 +2501,8 @@
         return nullptr;
 
       // Validate the resulting type.
-      TypeResolutionOptions options = TR_AllowUnboundGenerics;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+      options |= TypeResolutionFlags::InExpression;
       if (tc.validateType(expr->getCastTypeLoc(), CS.DC, options))
         return nullptr;
 
@@ -2523,8 +2524,8 @@
       auto &tc = CS.getTypeChecker();
       
       // Validate the resulting type.
-      TypeResolutionOptions options = TR_AllowUnboundGenerics;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+      options |= TypeResolutionFlags::InExpression;
       if (tc.validateType(expr->getCastTypeLoc(), CS.DC, options))
         return nullptr;
 
@@ -2548,8 +2549,8 @@
         return nullptr;
 
       // Validate the resulting type.
-      TypeResolutionOptions options = TR_AllowUnboundGenerics;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+      options |= TypeResolutionFlags::InExpression;
       if (tc.validateType(expr->getCastTypeLoc(), CS.DC, options))
         return nullptr;
 
@@ -2567,8 +2568,8 @@
     Type visitIsExpr(IsExpr *expr) {
       // Validate the type.
       auto &tc = CS.getTypeChecker();
-      TypeResolutionOptions options = TR_AllowUnboundGenerics;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+      options |= TypeResolutionFlags::InExpression;
       if (tc.validateType(expr->getCastTypeLoc(), CS.DC, options))
         return nullptr;
 
@@ -3572,7 +3573,7 @@
 
   // Keep track of all the unviable members.
   for (auto Can : LookupResult.UnviableCandidates)
-    Result.Impl.AllDecls.push_back(Can.first);
+    Result.Impl.AllDecls.push_back(Can.first.getDecl());
 
   // Keep track of the start of viable choices.
   Result.Impl.ViableStartIdx = Result.Impl.AllDecls.size();
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 469c620..25c2260 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -232,8 +232,10 @@
 
   // If the model type does not conform to the protocol, the bases are
   // unrelated.
-  auto conformance = tc.conformsToProtocol(modelTy, proto, dc,
-                                           ConformanceCheckFlags::InExpression);
+  auto conformance = tc.conformsToProtocol(
+                         modelTy, proto, dc,
+                         (ConformanceCheckFlags::InExpression|
+                          ConformanceCheckFlags::SkipConditionalRequirements));
   if (!conformance)
     return {SelfTypeRelationship::Unrelated, None};
 
@@ -362,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.
 ///
@@ -613,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;
         };
 
@@ -1068,12 +1084,14 @@
       if (auto nominalType2 = type2->getNominalOrBoundGenericNominal()) {
         if ((nominalType2->getName() ==
              cs.TC.Context.Id_OptionalNilComparisonType)) {
-          ++score1;
+          ++score2;
         }
-      } else if (auto nominalType1 = type1->getNominalOrBoundGenericNominal()) {
+      }
+
+      if (auto nominalType1 = type1->getNominalOrBoundGenericNominal()) {
         if ((nominalType1->getName() ==
              cs.TC.Context.Id_OptionalNilComparisonType)) {
-          ++score2;
+          ++score1;
         }
       }
     }
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index e5a406a..fd39811 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2395,13 +2395,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,
@@ -2582,6 +2575,27 @@
     return SolutionKind::Unsolved;
   }
 
+  /// Record the given conformance as the result, adding any conditional
+  /// requirements if necessary.
+  auto recordConformance = [&](ProtocolConformanceRef conformance) {
+    // Record the conformance.
+    CheckedConformances.push_back({getConstraintLocator(locator), conformance});
+
+    // This conformance may be conditional, in which case we need to consider
+    // those requirements as constraints too.
+    if (conformance.isConcrete()) {
+      unsigned index = 0;
+      for (const auto &req : conformance.getConditionalRequirements()) {
+        addConstraint(
+          req,
+          locator.withPathElement(
+            LocatorPathElt::getConditionalRequirementComponent(index++)));
+      }
+    }
+
+    return SolutionKind::Solved;
+  };
+
   // For purposes of argument type matching, existential types don't need to
   // conform -- they only need to contain the protocol, so check that
   // separately.
@@ -2590,38 +2604,18 @@
     if (auto conformance =
           TC.containsProtocol(type, protocol, DC,
                               ConformanceCheckFlags::InExpression)) {
-      CheckedConformances.push_back({getConstraintLocator(locator),
-                                     *conformance});
-      return SolutionKind::Solved;
+      return recordConformance(*conformance);
     }
     break;
   case ConstraintKind::ConformsTo:
   case ConstraintKind::LiteralConformsTo: {
     // Check whether this type conforms to the protocol.
     if (auto conformance =
-          TC.conformsToProtocol(type, protocol, DC,
-                                ConformanceCheckFlags::InExpression)) {
-      CheckedConformances.push_back({getConstraintLocator(locator),
-                                     *conformance});
-
-      // This conformance may be conditional, in which case we need to consider
-      // those requirements as constraints too.
-      //
-      // If we've got a normal conformance, we must've started with `type` in
-      // the context that declares the conformance, and so these requirements
-      // are automatically satisfied, and thus we can skip adding them. (This
-      // hacks around some representational problems caused by requirements
-      // being stored as interface types and the normal conformance's type being
-      // a contextual type. Once the latter is fixed and everything is interface
-      // types, this shouldn't be necessary.)
-      if (conformance->isConcrete() &&
-          conformance->getConcrete()->getKind() !=
-              ProtocolConformanceKind::Normal) {
-        for (auto req : conformance->getConditionalRequirements()) {
-          addConstraint(req, locator);
-        }
-      }
-      return SolutionKind::Solved;
+          TC.conformsToProtocol(
+                      type, protocol, DC,
+                      (ConformanceCheckFlags::InExpression|
+                       ConformanceCheckFlags::SkipConditionalRequirements))) {
+      return recordConformance(*conformance);
     }
     break;
   }
@@ -3088,34 +3082,35 @@
 
   // Local function that adds the given declaration if it is a
   // reasonable choice.
-  auto addChoice = [&](ValueDecl *cand, bool isBridged,
-                       bool isUnwrappedOptional) {
+  auto addChoice = [&](OverloadChoice candidate) {
+    auto decl = candidate.getDecl();
+    
     // If the result is invalid, skip it.
-    TC.validateDecl(cand);
-    if (cand->isInvalid()) {
+    TC.validateDecl(decl);
+    if (decl->isInvalid()) {
       result.markErrorAlreadyDiagnosed();
       return;
     }
 
     // FIXME: Deal with broken recursion
-    if (!cand->hasInterfaceType())
+    if (!decl->hasInterfaceType())
       return;
 
     // If the argument labels for this result are incompatible with
     // the call site, skip it.
-    if (!hasCompatibleArgumentLabels(cand)) {
+    if (!hasCompatibleArgumentLabels(decl)) {
       labelMismatch = true;
-      result.addUnviable(cand, MemberLookupResult::UR_LabelMismatch);
+      result.addUnviable(candidate, MemberLookupResult::UR_LabelMismatch);
       return;
     }
 
     // If our base is an existential type, we can't make use of any
     // member whose signature involves associated types.
     if (isExistential) {
-      if (auto *proto = cand->getDeclContext()
+      if (auto *proto = decl->getDeclContext()
               ->getAsProtocolOrProtocolExtensionContext()) {
-        if (!proto->isAvailableInExistential(cand)) {
-          result.addUnviable(cand,
+        if (!proto->isAvailableInExistential(decl)) {
+          result.addUnviable(candidate,
                              MemberLookupResult::UR_UnavailableInExistential);
           return;
         }
@@ -3125,18 +3120,17 @@
     // If the invocation's argument expression has a favored type,
     // use that information to determine whether a specific overload for
     // the candidate should be favored.
-    if (isa<ConstructorDecl>(cand) && favoredType &&
+    if (isa<ConstructorDecl>(decl) && favoredType &&
         result.FavoredChoice == ~0U) {
       // Only try and favor monomorphic initializers.
-      if (auto fnTypeWithSelf = cand->getInterfaceType()
-                                                      ->getAs<FunctionType>()) {
-        if (auto fnType = fnTypeWithSelf->getResult()
-                                                      ->getAs<FunctionType>()) {
+      if (auto fnTypeWithSelf = decl->getInterfaceType()
+                                                     ->getAs<FunctionType>()) {
+        if (auto fnType = fnTypeWithSelf->getResult()->getAs<FunctionType>()) {
           auto argType = fnType->getInput()->getWithoutParens();
-          argType = cand->getInnermostDeclContext()
+          argType = decl->getInnermostDeclContext()
                                                   ->mapTypeIntoContext(argType);
           if (argType->isEqual(favoredType))
-            if (!cand->getAttrs().isUnavailable(getASTContext()))
+            if (!decl->getAttrs().isUnavailable(getASTContext()))
               result.FavoredChoice = result.ViableCandidates.size();
         }
       }
@@ -3144,25 +3138,27 @@
 
     // See if we have an instance method, instance member or static method,
     // and check if it can be accessed on our base type.
-    if (cand->isInstanceMember()) {
-      if ((isa<FuncDecl>(cand) && !hasInstanceMethods) ||
-          (!isa<FuncDecl>(cand) && !hasInstanceMembers)) {
-        result.addUnviable(cand, MemberLookupResult::UR_InstanceMemberOnType);
+    if (decl->isInstanceMember()) {
+      if ((isa<FuncDecl>(decl) && !hasInstanceMethods) ||
+          (!isa<FuncDecl>(decl) && !hasInstanceMembers)) {
+        result.addUnviable(candidate,
+                           MemberLookupResult::UR_InstanceMemberOnType);
         return;
       }
 
     // If the underlying type of a typealias is fully concrete, it is legal
     // to access the type with a protocol metatype base.
     } else if (isExistential &&
-               isa<TypeAliasDecl>(cand) &&
-               !cast<TypeAliasDecl>(cand)->getInterfaceType()->getCanonicalType()
+               isa<TypeAliasDecl>(decl) &&
+               !cast<TypeAliasDecl>(decl)->getInterfaceType()->getCanonicalType()
                   ->hasTypeParameter()) {
 
       /* We're OK */
 
     } else {
       if (!hasStaticMembers) {
-        result.addUnviable(cand, MemberLookupResult::UR_TypeMemberOnInstance);
+        result.addUnviable(candidate,
+                           MemberLookupResult::UR_TypeMemberOnInstance);
         return;
       }
     }
@@ -3170,19 +3166,19 @@
     // If we have an rvalue base, make sure that the result isn't 'mutating'
     // (only valid on lvalues).
     if (!isMetatype &&
-        !baseTy->is<LValueType>() && cand->isInstanceMember()) {
-      if (auto *FD = dyn_cast<FuncDecl>(cand))
+        !baseTy->is<LValueType>() && decl->isInstanceMember()) {
+      if (auto *FD = dyn_cast<FuncDecl>(decl))
         if (FD->isMutating()) {
-          result.addUnviable(cand,
+          result.addUnviable(candidate,
                              MemberLookupResult::UR_MutatingMemberOnRValue);
           return;
         }
 
       // Subscripts and computed properties are ok on rvalues so long
       // as the getter is nonmutating.
-      if (auto storage = dyn_cast<AbstractStorageDecl>(cand)) {
+      if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
         if (storage->isGetterMutating()) {
-          result.addUnviable(cand,
+          result.addUnviable(candidate,
                              MemberLookupResult::UR_MutatingGetterOnRValue);
           return;
         }
@@ -3190,52 +3186,55 @@
     }
     
     // If the result's type contains delayed members, we need to force them now.
-    if (auto NT = dyn_cast<NominalType>(cand->getInterfaceType().getPointer())) {
+    if (auto NT = dyn_cast<NominalType>(decl->getInterfaceType().getPointer())){
       if (auto *NTD = dyn_cast<NominalTypeDecl>(NT->getDecl())) {
         TC.forceExternalDeclMembers(NTD);
       }
     }
 
+    // Otherwise, we're good, add the candidate to the list.
+    result.addViable(candidate);
+  };
+
+  // Local function that turns a ValueDecl into a properly configured
+  // OverloadChoice.
+  auto getOverloadChoice = [&](ValueDecl *cand, bool isBridged,
+                               bool isUnwrappedOptional) -> OverloadChoice {
     // If we're looking into an existential type, check whether this
     // result was found via dynamic lookup.
     if (isDynamicLookup) {
       assert(cand->getDeclContext()->isTypeContext() && "Dynamic lookup bug");
-
+      
       // We found this declaration via dynamic lookup, record it as such.
-      result.addViable(OverloadChoice::getDeclViaDynamic(baseTy, cand,
-                                                         functionRefKind));
-      return;
+      return OverloadChoice::getDeclViaDynamic(baseTy, cand, functionRefKind);
     }
-
+    
     // If we have a bridged type, we found this declaration via bridging.
-    if (isBridged) {
-      result.addViable(OverloadChoice::getDeclViaBridge(bridgedType, cand,
-                                                        functionRefKind));
-      return;
-    }
-
+    if (isBridged)
+      return OverloadChoice::getDeclViaBridge(bridgedType, cand,
+                                              functionRefKind);
+    
     // If we got the choice by unwrapping an optional type, unwrap the base
     // type.
     Type ovlBaseTy = baseTy;
     if (isUnwrappedOptional) {
       ovlBaseTy = MetatypeType::get(baseTy->castTo<MetatypeType>()
-        ->getInstanceType()
-        ->getAnyOptionalObjectType());
-      result.addViable(
-        OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
-                                                    functionRefKind));
-    } else {
-      result.addViable(OverloadChoice(ovlBaseTy, cand, functionRefKind));
+                                    ->getInstanceType()
+                                    ->getAnyOptionalObjectType());
+      return OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
+                                                         functionRefKind);
     }
+    
+    return OverloadChoice(ovlBaseTy, cand, functionRefKind);
   };
-
+  
   // Add all results from this lookup.
 retry_after_fail:
   labelMismatch = false;
   for (auto result : lookup)
-    addChoice(result.getValueDecl(),
-              /*isBridged=*/false,
-              /*isUnwrappedOptional=*/false);
+    addChoice(getOverloadChoice(result.getValueDecl(),
+                                /*isBridged=*/false,
+                                /*isUnwrappedOptional=*/false));
 
   // If the instance type is a bridged to an Objective-C type, perform
   // a lookup into that Objective-C type.
@@ -3258,9 +3257,9 @@
         continue;
       }
       
-      addChoice(result.getValueDecl(),
-                /*isBridged=*/true,
-                /*isUnwrappedOptional=*/false);
+      addChoice(getOverloadChoice(result.getValueDecl(),
+                                  /*isBridged=*/true,
+                                  /*isUnwrappedOptional=*/false));
     }
   }
 
@@ -3274,9 +3273,9 @@
       if (objectType->mayHaveMembers()) {
         LookupResult &optionalLookup = lookupMember(objectType, memberName);
         for (auto result : optionalLookup)
-          addChoice(result.getValueDecl(),
-                    /*bridged*/false,
-                    /*isUnwrappedOptional=*/true);
+          addChoice(getOverloadChoice(result.getValueDecl(),
+                                      /*bridged*/false,
+                                      /*isUnwrappedOptional=*/true));
       }
     }
   }
@@ -3318,7 +3317,9 @@
       if (!cand->hasInterfaceType())
         continue;
 
-      result.addUnviable(cand, MemberLookupResult::UR_Inaccessible);
+      result.addUnviable(getOverloadChoice(cand, /*isBridged=*/false,
+                                           /*isUnwrappedOptional=*/false),
+                         MemberLookupResult::UR_Inaccessible);
     }
   }
   
@@ -4185,7 +4186,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)) {
@@ -4213,6 +4228,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;
   }
 
@@ -4223,23 +4243,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;
@@ -4721,15 +4736,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;
 }
 
@@ -4738,31 +4753,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/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 88e0e74..daf43c2 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -76,6 +76,8 @@
     case ApplyArgToParam:
     case OpenedGeneric:
     case KeyPathComponent:
+    case ConditionalRequirement:
+    case TypeParameterRequirement:
       if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
         id.AddInteger(elt.getValue());
         if (numValues > 1)
@@ -238,6 +240,14 @@
     case OpenedGeneric:
       out << "opened generic";
       break;
+
+    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 43c280f..b8f3794 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -123,6 +123,10 @@
     OpenedGeneric,
     /// A component of a key path.
     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
@@ -161,6 +165,8 @@
     case NamedTupleElement:
     case TupleElement:
     case KeyPathComponent:
+    case ConditionalRequirement:
+    case TypeParameterRequirement:
       return 1;
 
     case ApplyArgToParam:
@@ -213,6 +219,8 @@
     case Requirement:
     case Witness:
     case KeyPathComponent:
+    case ConditionalRequirement:
+    case TypeParameterRequirement:
       return 0;
 
     case FunctionArgument:
@@ -344,6 +352,15 @@
       return PathElement(KeyPathComponent, position);
     }
 
+    /// Get a path element for a conditional requirement.
+    static PathElement getConditionalRequirementComponent(unsigned index) {
+      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 2a42ea7..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);
@@ -893,7 +905,7 @@
   if (auto typeDecl = dyn_cast<TypeDecl>(value)) {
     // Resolve the reference to this type declaration in our current context.
     auto type = TC.resolveTypeInContext(typeDecl, nullptr, DC,
-                                        TR_InExpression,
+                                        TypeResolutionFlags::InExpression,
                                         /*isSpecialized=*/false);
 
     // Open the type.
@@ -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 9be37fe..506a3d3 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:
@@ -849,9 +851,9 @@
     UR_Inaccessible,
   };
   
-  /// This is a list of considered, but rejected, candidates, along with a
+  /// This is a list of considered (but rejected) candidates, along with a
   /// reason for their rejection.
-  SmallVector<std::pair<ValueDecl*, UnviableReason>, 4> UnviableCandidates;
+  SmallVector<std::pair<OverloadChoice, UnviableReason>, 4> UnviableCandidates;
 
 
   /// Mark this as being an already-diagnosed error and return itself.
@@ -864,8 +866,8 @@
     ViableCandidates.push_back(candidate);
   }
   
-  void addUnviable(ValueDecl *VD, UnviableReason reason) {
-    UnviableCandidates.push_back({VD, reason});
+  void addUnviable(OverloadChoice candidate, UnviableReason reason) {
+    UnviableCandidates.push_back({candidate, reason});
   }
   
   OverloadChoice *getFavoredChoice() {
@@ -1996,6 +1998,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 +2555,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 +2566,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/ITCDecl.cpp b/lib/Sema/ITCDecl.cpp
index fd57db4..854bb9d 100644
--- a/lib/Sema/ITCDecl.cpp
+++ b/lib/Sema/ITCDecl.cpp
@@ -37,9 +37,9 @@
     inheritanceClause = typeDecl->getInherited();
     if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
       dc = nominal;
-      options |= (TR_GenericSignature |
-                  TR_InheritanceClause |
-                  TR_AllowUnavailableProtocol);
+      options |= TypeResolutionFlags::GenericSignature;
+      options |= TypeResolutionFlags::InheritanceClause;
+      options |= TypeResolutionFlags::AllowUnavailableProtocol;
     } else {
       dc = typeDecl->getDeclContext();
 
@@ -48,13 +48,13 @@
         // signature of the enclosing entity.
         if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
           dc = nominal;
-          options |= TR_GenericSignature;
+          options |= TypeResolutionFlags::GenericSignature;
         } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
           dc = ext;
-          options |= TR_GenericSignature;
+          options |= TypeResolutionFlags::GenericSignature;
         } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
           dc = func;
-          options |= TR_GenericSignature;
+          options |= TypeResolutionFlags::GenericSignature;
         } else if (!dc->isModuleScopeContext()) {
           // Skip the generic parameter's context entirely.
           dc = dc->getParent();
@@ -65,9 +65,9 @@
     auto ext = decl.get<ExtensionDecl *>();
     inheritanceClause = ext->getInherited();
     dc = ext;
-    options |= (TR_GenericSignature |
-                TR_InheritanceClause |
-                TR_AllowUnavailableProtocol);
+    options |= TypeResolutionFlags::GenericSignature;
+    options |= TypeResolutionFlags::InheritanceClause;
+    options |= TypeResolutionFlags::AllowUnavailableProtocol;
   }
 
   return std::make_tuple(options, dc, inheritanceClause);
@@ -340,9 +340,12 @@
   if (auto typeAliasDecl = dyn_cast<TypeAliasDecl>(typeDecl)) {
     if (typeAliasDecl->getDeclContext()->isModuleScopeContext() &&
         typeAliasDecl->getGenericParams() == nullptr) {
-      TypeResolutionOptions options = TR_TypeAliasUnderlyingType;
-      if (typeAliasDecl->getFormalAccess() <= AccessLevel::FilePrivate)
-        options |= TR_KnownNonCascadingDependency;
+      TypeResolutionOptions options =
+                                   TypeResolutionFlags::TypeAliasUnderlyingType;
+      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/ITCType.cpp b/lib/Sema/ITCType.cpp
index 7033d9f..598fbb6 100644
--- a/lib/Sema/ITCType.cpp
+++ b/lib/Sema/ITCType.cpp
@@ -54,7 +54,7 @@
         // If we're only looking to resolve the structure of the type,
         // don't walk into generic arguments. They don't affect the
         // structure.
-        if (Options.contains(TR_ResolveStructure) &&
+        if (Options.contains(TypeResolutionFlags::ResolveStructure) &&
             isa<GenericIdentTypeRepr>(ident))
           return false;
       }
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/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index ee9f0a2..317b6f2 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -22,7 +22,6 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "swift/AST/Availability.h"
 #include "swift/AST/FunctionRefKind.h"
-#include "swift/AST/Type.h"
 #include "swift/AST/Types.h"
 
 namespace swift {
@@ -47,10 +46,6 @@
   BaseType,
   /// \brief The overload choice selects a key path subscripting operation.
   KeyPathApplication,
-  /// \brief The overload choice indexes into a tuple. Index zero will
-  /// have the value of this enumerator, index one will have the value of this
-  /// enumerator + 1, and so on. Thus, this enumerator must always be last.
-  TupleIndex,
   /// \brief The overload choice selects a particular declaration that
   /// was found by bridging the base value type to its Objective-C
   /// class type.
@@ -58,33 +53,43 @@
   /// \brief The overload choice selects a particular declaration that
   /// was found by unwrapping an optional context type.
   DeclViaUnwrappedOptional,
+  /// \brief The overload choice indexes into a tuple. Index zero will
+  /// have the value of this enumerator, index one will have the value of this
+  /// enumerator + 1, and so on. Thus, this enumerator must always be last.
+  TupleIndex,
 };
 
 /// \brief Describes a particular choice within an overload set.
 ///
-/// 
 class OverloadChoice {
   enum : unsigned {
-    /// Indicates whether this declaration was bridged, turning a
+    /// Indicates that this is a normal "Decl" kind, or isn't a decl.
+    IsDecl = 0x00,
+    /// Indicates that this declaration was bridged, turning a
     /// "Decl" kind into "DeclViaBridge" kind.
-    IsBridgedBit = 0x02,
-    /// Indicates whether this declaration was resolved by unwrapping an
+    IsDeclViaBridge = 0x01,
+    /// Indicates that this declaration was resolved by unwrapping an
     /// optional context type, turning a "Decl" kind into
     /// "DeclViaUnwrappedOptional".
-    IsUnwrappedOptionalBit = 0x04,
-    
-    // IsBridged and IsUnwrappedOptional are mutually exclusive, so there is
-    // room for another mutually exclusive OverloadChoiceKind to be packed into
-    // those two bits.
+    IsDeclViaUnwrappedOptional = 0x02,
+    /// Indicates that this declaration was dynamic, turning a
+    /// "Decl" kind into "DeclViaDynamic" kind.
+    IsDeclViaDynamic = 0x03
   };
 
   /// \brief The base type to be used when referencing the declaration
   /// along with the two bits above.
-  llvm::PointerIntPair<Type, 3, unsigned> BaseAndBits;
+  llvm::PointerIntPair<Type, 3, unsigned> BaseAndDeclKind;
 
-  /// \brief Either the declaration pointer (if the low bit is clear) or the
-  /// overload choice kind shifted two bits with the low bit set.
-  uintptr_t DeclOrKind;
+  /// We mash together OverloadChoiceKind with tuple indices into a single
+  /// integer representation.
+  typedef llvm::PointerEmbeddedInt<uint32_t, 29>
+    OverloadChoiceKindWithTupleIndex;
+  
+  /// \brief Either the declaration pointer or the overload choice kind.  The
+  /// second case is represented as an OverloadChoiceKind, but has additional
+  /// values at the top end that represent the tuple index.
+  llvm::PointerUnion<ValueDecl*, OverloadChoiceKindWithTupleIndex> DeclOrKind;
 
   /// The kind of function reference.
   /// FIXME: This needs two bits. Can we pack them somewhere?
@@ -92,23 +97,22 @@
 
 public:
   OverloadChoice()
-    : BaseAndBits(nullptr, 0), DeclOrKind(0),
+    : BaseAndDeclKind(nullptr, 0), DeclOrKind(0),
       TheFunctionRefKind(FunctionRefKind::Unapplied) {}
 
   OverloadChoice(Type base, ValueDecl *value,
                  FunctionRefKind functionRefKind)
-    : BaseAndBits(base, 0),
+    : BaseAndDeclKind(base, 0),
       TheFunctionRefKind(functionRefKind) {
     assert(!base || !base->hasTypeParameter());
     assert((reinterpret_cast<uintptr_t>(value) & (uintptr_t)0x03) == 0 &&
            "Badly aligned decl");
     
-    DeclOrKind = reinterpret_cast<uintptr_t>(value);
+    DeclOrKind = value;
   }
 
   OverloadChoice(Type base, OverloadChoiceKind kind)
-      : BaseAndBits(base, 0),
-        DeclOrKind((uintptr_t)kind << 2 | (uintptr_t)0x03),
+      : BaseAndDeclKind(base, 0), DeclOrKind(uint32_t(kind)),
         TheFunctionRefKind(FunctionRefKind::Unapplied) {
     assert(base && "Must have a base type for overload choice");
     assert(!base->hasTypeParameter());
@@ -120,19 +124,17 @@
   }
 
   OverloadChoice(Type base, unsigned index)
-      : BaseAndBits(base, 0),
-        DeclOrKind(((uintptr_t)index
-                    + (uintptr_t)OverloadChoiceKind::TupleIndex) << 2
-                    | (uintptr_t)0x03),
+      : BaseAndDeclKind(base, 0),
+        DeclOrKind(uint32_t(OverloadChoiceKind::TupleIndex)+index),
         TheFunctionRefKind(FunctionRefKind::Unapplied) {
     assert(base->getRValueType()->is<TupleType>() && "Must have tuple type");
   }
 
   bool isInvalid() const {
-    return BaseAndBits.getPointer().isNull()
-      && BaseAndBits.getInt() == 0
-      && DeclOrKind == 0
-      && TheFunctionRefKind == FunctionRefKind::Unapplied;
+    return BaseAndDeclKind.getPointer().isNull() &&
+           BaseAndDeclKind.getInt() == 0 &&
+           DeclOrKind.isNull() &&
+           TheFunctionRefKind == FunctionRefKind::Unapplied;
   }
 
   /// Retrieve an overload choice for a declaration that was found via
@@ -140,8 +142,9 @@
   static OverloadChoice getDeclViaDynamic(Type base, ValueDecl *value,
                                           FunctionRefKind functionRefKind) {
     OverloadChoice result;
-    result.BaseAndBits.setPointer(base);
-    result.DeclOrKind = reinterpret_cast<uintptr_t>(value) | 0x02;
+    result.BaseAndDeclKind.setPointer(base);
+    result.BaseAndDeclKind.setInt(IsDeclViaDynamic);
+    result.DeclOrKind = value;
     result.TheFunctionRefKind = functionRefKind;
     return result;
   }
@@ -151,76 +154,58 @@
   static OverloadChoice getDeclViaBridge(Type base, ValueDecl *value,
                                          FunctionRefKind functionRefKind) {
     OverloadChoice result;
-    result.BaseAndBits.setPointer(base);
-    result.BaseAndBits.setInt(IsBridgedBit);
-    result.DeclOrKind = reinterpret_cast<uintptr_t>(value);
+    result.BaseAndDeclKind.setPointer(base);
+    result.BaseAndDeclKind.setInt(IsDeclViaBridge);
+    result.DeclOrKind = value;
     result.TheFunctionRefKind = functionRefKind;
     return result;
   }
 
   /// Retrieve an overload choice for a declaration that was found
   /// by unwrapping an optional context type.
-  static OverloadChoice getDeclViaUnwrappedOptional(
-      Type base,
-      ValueDecl *value,
-      FunctionRefKind functionRefKind) {
+  static OverloadChoice
+  getDeclViaUnwrappedOptional(Type base, ValueDecl *value,
+                              FunctionRefKind functionRefKind) {
     OverloadChoice result;
-    result.BaseAndBits.setPointer(base);
-    result.BaseAndBits.setInt(IsUnwrappedOptionalBit);
-    result.DeclOrKind = reinterpret_cast<uintptr_t>(value);
+    result.BaseAndDeclKind.setPointer(base);
+    result.BaseAndDeclKind.setInt(IsDeclViaUnwrappedOptional);
+    result.DeclOrKind = value;
     result.TheFunctionRefKind = functionRefKind;
     return result;
   }
 
   /// \brief Retrieve the base type used to refer to the declaration.
-  Type getBaseType() const { return BaseAndBits.getPointer(); }
+  Type getBaseType() const {
+    return BaseAndDeclKind.getPointer();
+  }
   
   /// \brief Determines the kind of overload choice this is.
   OverloadChoiceKind getKind() const {
-    switch (DeclOrKind & 0x03) {
-    case 0x00: 
-      if (BaseAndBits.getInt() & IsBridgedBit)
-        return OverloadChoiceKind::DeclViaBridge;
-      if (BaseAndBits.getInt() & IsUnwrappedOptionalBit)
+    if (DeclOrKind.is<ValueDecl*>()) {
+      switch (BaseAndDeclKind.getInt()) {
+      case IsDeclViaBridge: return OverloadChoiceKind::DeclViaBridge;
+      case IsDeclViaDynamic: return OverloadChoiceKind::DeclViaDynamic;
+      case IsDeclViaUnwrappedOptional:
         return OverloadChoiceKind::DeclViaUnwrappedOptional;
-
-      return OverloadChoiceKind::Decl;
-      
-    case 0x02: return OverloadChoiceKind::DeclViaDynamic;
-    case 0x03: {
-      uintptr_t value = DeclOrKind >> 2;
-      if (value >= (uintptr_t)OverloadChoiceKind::TupleIndex)
-        return OverloadChoiceKind::TupleIndex;
-
-      return (OverloadChoiceKind)value;
+      default: return OverloadChoiceKind::Decl;
+      }
     }
 
-    default: llvm_unreachable("basic math has escaped me");
-    }
+    uint32_t kind = DeclOrKind.get<OverloadChoiceKindWithTupleIndex>();
+    if (kind >= (uint32_t)OverloadChoiceKind::TupleIndex)
+      return OverloadChoiceKind::TupleIndex;
+
+    return (OverloadChoiceKind)kind;
   }
 
   /// Determine whether this choice is for a declaration.
   bool isDecl() const {
-    switch (getKind()) {
-    case OverloadChoiceKind::Decl:
-    case OverloadChoiceKind::DeclViaDynamic:
-    case OverloadChoiceKind::DeclViaBridge:
-    case OverloadChoiceKind::DeclViaUnwrappedOptional:
-      return true;
-
-    case OverloadChoiceKind::BaseType:
-    case OverloadChoiceKind::TupleIndex:
-    case OverloadChoiceKind::KeyPathApplication:
-      return false;
-    }
-
-    llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
+    return DeclOrKind.is<ValueDecl*>();
   }
 
   /// \brief Retrieve the declaration that corresponds to this overload choice.
   ValueDecl *getDecl() const {
-    assert(isDecl() && "Not a declaration");
-    return reinterpret_cast<ValueDecl *>(DeclOrKind & ~(uintptr_t)0x03);
+    return DeclOrKind.get<ValueDecl*>();
   }
   
   /// Get the name of the overload choice.
@@ -230,12 +215,13 @@
   /// choice.
   unsigned getTupleIndex() const {
     assert(getKind() == OverloadChoiceKind::TupleIndex);
-    return (DeclOrKind >> 2) - (uintptr_t)OverloadChoiceKind::TupleIndex;
+    uint32_t kind = DeclOrKind.get<OverloadChoiceKindWithTupleIndex>();
+    return kind-(uint32_t)OverloadChoiceKind::TupleIndex;
   }
 
   /// \brief Retrieves an opaque choice that ignores the base type.
   void *getOpaqueChoiceSimple() const {
-    return reinterpret_cast<void*>(DeclOrKind);
+    return DeclOrKind.getOpaqueValue();
   }
 
   FunctionRefKind getFunctionRefKind() const {
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/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 173a587..eeebf92 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -1979,8 +1979,7 @@
 
 void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
   TypeLoc &ProtoTypeLoc = attr->getProtocolType();
-  TypeResolutionOptions options;
-  options |= TR_AllowUnboundGenerics;
+  auto options = TypeResolutionFlags::AllowUnboundGenerics;
 
   DeclContext *DC = D->getDeclContext();
   Type T = TC.resolveType(ProtoTypeLoc.getTypeRepr(),
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index a627797..ab4641d 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1009,10 +1009,10 @@
 
   // Validate the parameters.
   TypeResolutionOptions options;
-  options |= TR_AllowUnspecifiedTypes;
-  options |= TR_AllowUnboundGenerics;
-  options |= TR_InExpression;
-  options |= TR_AllowIUO;
+  options |= TypeResolutionFlags::AllowUnspecifiedTypes;
+  options |= TypeResolutionFlags::AllowUnboundGenerics;
+  options |= TypeResolutionFlags::InExpression;
+  options |= TypeResolutionFlags::AllowIUO;
   bool hadParameterError = false;
 
   GenericTypeToArchetypeResolver resolver(closure);
@@ -1030,7 +1030,7 @@
   // Validate the result type, if present.
   if (closure->hasExplicitResultType() &&
       TC.validateType(closure->getExplicitResultTypeLoc(), DC,
-                      TR_InExpression, &resolver)) {
+                      TypeResolutionFlags::InExpression, &resolver)) {
     closure->setType(ErrorType::get(TC.Context));
     return false;
   }
@@ -1112,9 +1112,9 @@
     // Resolve the TypeRepr to get the base type for the lookup.
     // Disable availability diagnostics here, because the final
     // TypeRepr will be resolved again when generating constraints.
-    TypeResolutionOptions options = TR_AllowUnboundGenerics;
-    options |= TR_InExpression;
-    options |= TR_AllowUnavailable;
+    TypeResolutionOptions options = TypeResolutionFlags::AllowUnboundGenerics;
+    options |= TypeResolutionFlags::InExpression;
+    options |= TypeResolutionFlags::AllowUnavailable;
     auto BaseTy = TC.resolveType(InnerTypeRepr, DC, options);
 
     if (BaseTy && BaseTy->mayHaveMembers()) {
@@ -2210,11 +2210,10 @@
   }
 
   if (resultTy) {
-    TypeResolutionOptions options;
-    options |= TR_OverrideType;
-    options |= TR_InExpression;
+    TypeResolutionOptions options = TypeResolutionFlags::OverrideType;
+    options |= TypeResolutionFlags::InExpression;
     if (isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())) {
-      options |= TR_EditorPlaceholder;
+      options |= TypeResolutionFlags::EditorPlaceholder;
     }
 
     // FIXME: initTy should be the same as resultTy; now that typeCheckExpression()
@@ -2433,10 +2432,9 @@
 
       // Apply the solution to the iteration pattern as well.
       Pattern *pattern = Stmt->getPattern();
-      TypeResolutionOptions options;
-      options |= TR_OverrideType;
-      options |= TR_EnumerationVariable;
-      options |= TR_InExpression;
+      TypeResolutionOptions options = TypeResolutionFlags::OverrideType;
+      options |= TypeResolutionFlags::EnumerationVariable;
+      options |= TypeResolutionFlags::InExpression;
       if (tc.coercePatternToType(pattern, cs.DC, InitType, options)) {
         return nullptr;
       }
@@ -2606,9 +2604,9 @@
 
     // Check the pattern, it allows unspecified types because the pattern can
     // provide type information.
-    TypeResolutionOptions options = TR_InExpression;
-    options |= TR_AllowUnspecifiedTypes;
-    options |= TR_AllowUnboundGenerics;
+    TypeResolutionOptions options = TypeResolutionFlags::InExpression;
+    options |= TypeResolutionFlags::AllowUnspecifiedTypes;
+    options |= TypeResolutionFlags::AllowUnboundGenerics;
     if (typeCheckPattern(pattern, dc, options)) {
       typeCheckPatternFailed();
       continue;
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 1422992..fee6907 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -297,27 +297,27 @@
   DeclContext *DC;
   if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
     DC = nominal;
-    options |= (TR_GenericSignature |
-                TR_InheritanceClause |
-                TR_AllowUnavailableProtocol);
+    options |= TypeResolutionFlags::GenericSignature;
+    options |= TypeResolutionFlags::InheritanceClause;
+    options |= TypeResolutionFlags::AllowUnavailableProtocol;
   } else if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
     DC = ext;
-    options |= (TR_GenericSignature |
-                TR_InheritanceClause |
-                TR_AllowUnavailableProtocol);
+    options |= TypeResolutionFlags::GenericSignature;
+    options |= TypeResolutionFlags::InheritanceClause;
+    options |= TypeResolutionFlags::AllowUnavailableProtocol;
   } else if (isa<GenericTypeParamDecl>(decl)) {
     // For generic parameters, we want name lookup to look at just the
     // signature of the enclosing entity.
     DC = decl->getDeclContext();
     if (auto nominal = dyn_cast<NominalTypeDecl>(DC)) {
       DC = nominal;
-      options |= TR_GenericSignature;
+      options |= TypeResolutionFlags::GenericSignature;
     } else if (auto ext = dyn_cast<ExtensionDecl>(DC)) {
       DC = ext;
-      options |= TR_GenericSignature;
+      options |= TypeResolutionFlags::GenericSignature;
     } else if (auto func = dyn_cast<AbstractFunctionDecl>(DC)) {
       DC = func;
-      options |= TR_GenericSignature;
+      options |= TypeResolutionFlags::GenericSignature;
     } else if (!DC->isModuleScopeContext()) {
       // Skip the generic parameter's context entirely.
       DC = DC->getParent();
@@ -1117,13 +1117,13 @@
   // In particular, it's /not/ correct to check the PBD's DeclContext because
   // top-level variables in a script file are accessible from other files,
   // even though the PBD is inside a TopLevelCodeDecl.
-  TypeResolutionOptions options = TR_InExpression;
+  TypeResolutionOptions options = TypeResolutionFlags::InExpression;
 
-  options |= TR_AllowIUO;
+  options |= TypeResolutionFlags::AllowIUO;
   if (binding->getInit(entryNumber)) {
     // If we have an initializer, we can also have unknown types.
-    options |= TR_AllowUnspecifiedTypes;
-    options |= TR_AllowUnboundGenerics;
+    options |= TypeResolutionFlags::AllowUnspecifiedTypes;
+    options |= TypeResolutionFlags::AllowUnboundGenerics;
   }
   if (tc.typeCheckPattern(pattern, binding->getDeclContext(), options)) {
     setBoundVarsTypeError(pattern, tc.Context);
@@ -4284,10 +4284,10 @@
     GenericTypeToArchetypeResolver resolver(SD);
 
     bool isInvalid = TC.validateType(SD->getElementTypeLoc(), SD,
-                                     TR_AllowIUO,
+                                     TypeResolutionFlags::AllowIUO,
                                      &resolver);
     TypeResolutionOptions options;
-    options |= TR_SubscriptParameters;
+    options |= TypeResolutionFlags::SubscriptParameters;
 
     isInvalid |= TC.typeCheckParameterList(SD->getIndices(), SD,
                                            options,
@@ -4863,9 +4863,9 @@
 
     bool badType = false;
     if (!FD->getBodyResultTypeLoc().isNull()) {
-      TypeResolutionOptions options = TR_AllowIUO;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowIUO;
       if (FD->hasDynamicSelf())
-        options |= TR_DynamicSelfResult;
+        options |= TypeResolutionFlags::DynamicSelfResult;
 
       if (TC.validateType(FD->getBodyResultTypeLoc(), FD, options,
                           &resolver)) {
@@ -6830,7 +6830,7 @@
       
       if (!EED->getArgumentTypeLoc().isNull()) {
         if (TC.validateType(EED->getArgumentTypeLoc(), EED->getDeclContext(),
-                            TR_EnumCase)) {
+                            TypeResolutionFlags::EnumCase)) {
           EED->setInterfaceType(ErrorType::get(TC.Context));
           EED->setInvalid();
           return;
@@ -7357,9 +7357,11 @@
 
 /// Validate the underlying type of the given typealias.
 static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) {
-  TypeResolutionOptions options = TR_TypeAliasUnderlyingType;
-  if (typeAlias->getFormalAccess() <= AccessLevel::FilePrivate)
-    options |= TR_KnownNonCascadingDependency;
+  TypeResolutionOptions options = TypeResolutionFlags::TypeAliasUnderlyingType;
+  if (!typeAlias->getDeclContext()->isCascadingContextForLookup(
+        /*functionsAreNonCascading*/true)) {
+     options |= TypeResolutionFlags::KnownNonCascadingDependency;
+  }
 
   if (typeAlias->getDeclContext()->isModuleScopeContext() &&
       typeAlias->getGenericParams() == nullptr) {
@@ -7832,20 +7834,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 |= TR_KnownNonCascadingDependency;
 
+        ProtocolRequirementTypeResolver resolver;
         if (validateType(typealias->getUnderlyingTypeLoc(),
-                         typealias, options, &resolver)) {
+                         typealias, TypeResolutionOptions(), &resolver)) {
           typealias->setInvalid();
           typealias->getUnderlyingTypeLoc().setInvalidType(Context);
         }
@@ -8824,9 +8822,11 @@
   // complete.
   auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
     auto targetType = target->getDeclaredInterfaceType();
-    if (auto ref = conformsToProtocol(targetType, protocol, target,
-                                      ConformanceCheckFlags::Used,
-                                      SourceLoc())) {
+    if (auto ref = conformsToProtocol(
+                        targetType, protocol, target,
+                        (ConformanceCheckFlags::Used|
+                         ConformanceCheckFlags::SkipConditionalRequirements),
+                         SourceLoc())) {
       if (auto *conformance = ref->getConcrete()->getRootNormalConformance()) {
         if (conformance->isIncomplete()) {
           // Check conformance, forcing synthesis.
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 6943b73..9feb689 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -262,7 +262,7 @@
             isa<AbstractFunctionDecl>(lookupDC) ||
             isa<SubscriptDecl>(lookupDC)) &&
            "not a proper generic parameter context?");
-    options = TR_GenericSignature;
+    options = TypeResolutionFlags::GenericSignature;
   }    
 
   // First, add the generic parameters to the generic signature builder.
@@ -354,6 +354,48 @@
   }
 }
 
+std::string
+TypeChecker::gatherGenericParamBindingsText(
+                                ArrayRef<Type> types,
+                                ArrayRef<GenericTypeParamType *> genericParams,
+                                TypeSubstitutionFn substitutions) {
+  llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams;
+  for (auto type : types) {
+    type.visit([&](Type type) {
+      if (auto gp = type->getAs<GenericTypeParamType>()) {
+        knownGenericParams.insert(
+            gp->getCanonicalType()->castTo<GenericTypeParamType>());
+      }
+    });
+  }
+
+  if (knownGenericParams.empty())
+    return "";
+
+  SmallString<128> result;
+  for (auto gp : genericParams) {
+    auto canonGP = gp->getCanonicalType()->castTo<GenericTypeParamType>();
+    if (!knownGenericParams.count(canonGP))
+      continue;
+
+    if (result.empty())
+      result += " [with ";
+    else
+      result += ", ";
+    result += gp->getName().str();
+    result += " = ";
+
+    auto type = substitutions(canonGP);
+    if (!type)
+      return "";
+
+    result += type.getString();
+  }
+
+  result += "]";
+  return result.str().str();
+}
+
 void
 TypeChecker::prepareGenericParamList(GenericParamList *gp,
                                      DeclContext *dc) {
@@ -471,9 +513,9 @@
   if (auto fn = dyn_cast<FuncDecl>(func)) {
     if (!fn->getBodyResultTypeLoc().isNull()) {
       // Check the result type of the function.
-      TypeResolutionOptions options = TR_AllowIUO;
+      TypeResolutionOptions options = TypeResolutionFlags::AllowIUO;
       if (fn->hasDynamicSelf())
-        options |= TR_DynamicSelfResult;
+        options |= TypeResolutionFlags::DynamicSelfResult;
 
       if (tc.validateType(fn->getBodyResultTypeLoc(), fn, options, &resolver)) {
         badType = true;
@@ -931,7 +973,7 @@
 
   // Check the element type.
   badType |= tc.validateType(subscript->getElementTypeLoc(), subscript,
-                             TR_AllowIUO, &resolver);
+                             TypeResolutionFlags::AllowIUO, &resolver);
 
   // Infer requirements from it.
   if (genericParams && builder) {
@@ -946,9 +988,7 @@
 
   // Check the indices.
   auto params = subscript->getIndices();
-
-  TypeResolutionOptions options;
-  options |= TR_SubscriptParameters;
+  TypeResolutionOptions options = TypeResolutionFlags::SubscriptParameters;
 
   badType |= tc.typeCheckParameterList(params, subscript,
                                        options,
@@ -1216,7 +1256,9 @@
 
 RequirementCheckResult TypeChecker::checkGenericArguments(
     DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner,
-    GenericSignature *genericSig, TypeSubstitutionFn substitutions,
+    ArrayRef<GenericTypeParamType *> genericParams,
+    ArrayRef<Requirement> requirements,
+    TypeSubstitutionFn substitutions,
     LookupConformanceFn conformances,
     UnsatisfiedDependency *unsatisfiedDependency,
     ConformanceCheckOptions conformanceOptions,
@@ -1224,13 +1266,16 @@
     SubstOptions options) {
   bool valid = true;
 
+  // We handle any conditional requirements ourselves.
+  conformanceOptions |= ConformanceCheckFlags::SkipConditionalRequirements;
+
   struct RequirementSet {
     ArrayRef<Requirement> Requirements;
     SmallVector<ParentConditionalConformance, 4> Parents;
   };
 
   SmallVector<RequirementSet, 8> pendingReqs;
-  pendingReqs.push_back({genericSig->getRequirements(), {}});
+  pendingReqs.push_back({requirements, {}});
 
   while (!pendingReqs.empty()) {
     auto current = pendingReqs.pop_back_val();
@@ -1352,9 +1397,15 @@
       if (loc.isValid()) {
         // FIXME: Poor source-location information.
         diagnose(loc, diagnostic, owner, firstType, secondType);
+
+        std::string genericParamBindingsText;
+        if (!genericParams.empty()) {
+          genericParamBindingsText =
+            gatherGenericParamBindingsText(
+              {rawFirstType, rawSecondType}, genericParams, substitutions);
+        }
         diagnose(noteLoc, diagnosticNote, rawFirstType, rawSecondType,
-                 genericSig->gatherGenericParamBindingsText(
-                     {rawFirstType, rawSecondType}, substitutions));
+                 genericParamBindingsText);
 
         ParentConditionalConformance::diagnoseConformanceStack(Diags, noteLoc,
                                                                current.Parents);
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index 4bc6af7..aa8533a 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -106,6 +106,7 @@
       ConformanceCheckOptions conformanceOptions;
       if (Options.contains(NameLookupFlags::KnownPrivate))
         conformanceOptions |= ConformanceCheckFlags::InExpression;
+      conformanceOptions |= ConformanceCheckFlags::SkipConditionalRequirements;
 
       DeclContext *foundDC = found->getDeclContext();
 
@@ -430,6 +431,7 @@
     ConformanceCheckOptions conformanceOptions;
     if (options.contains(NameLookupFlags::KnownPrivate))
       conformanceOptions |= ConformanceCheckFlags::InExpression;
+    conformanceOptions |= ConformanceCheckFlags::SkipConditionalRequirements;
 
     for (AssociatedTypeDecl *assocType : inferredAssociatedTypes) {
       // If the type does not actually conform to the protocol, skip this
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 8d3e48f..215098f 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -430,7 +430,8 @@
     auto *repr = IdentTypeRepr::create(TC.Context, components);
       
     // See if the repr resolves to a type.
-    Type ty = TC.resolveIdentifierType(DC, repr, TR_AllowUnboundGenerics,
+    Type ty = TC.resolveIdentifierType(DC, repr,
+                                      TypeResolutionFlags::AllowUnboundGenerics,
                                        /*diagnoseErrors*/false, &resolver,
                                        nullptr);
     
@@ -549,7 +550,7 @@
       auto *prefixRepr = IdentTypeRepr::create(TC.Context, components);
       // See first if the entire repr resolves to a type.
       Type enumTy = TC.resolveIdentifierType(DC, prefixRepr,
-                                             TR_AllowUnboundGenerics,
+                                      TypeResolutionFlags::AllowUnboundGenerics,
                                              /*diagnoseErrors*/false, &resolver,
                                              nullptr);
       if (!dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal()))
@@ -709,11 +710,11 @@
   // If the element is a variadic parameter, resolve the parameter type as if
   // it were in non-parameter position, since we want functions to be
   // @escaping in this case.
-  auto elementOptions = (options |
-                         (decl->isVariadic() ? TR_VariadicFunctionInput
-                                             : TR_FunctionInput));
+  auto elementOptions = (options | (decl->isVariadic()
+                                    ? TypeResolutionFlags::VariadicFunctionInput
+                                    : TypeResolutionFlags::FunctionInput));
   if (!decl->isVariadic())
-    elementOptions |= TR_AllowIUO;
+    elementOptions |= TypeResolutionFlags::AllowIUO;
 
   bool hadError = false;
 
@@ -778,7 +779,7 @@
     // as well to get the ParamDecl marked invalid and to get an ErrorType.
     if (!type) {
       // Closure argument lists are allowed to be missing types.
-      if (options & TR_InExpression)
+      if (options & TypeResolutionFlags::InExpression)
         continue;
       param->setInvalid();
     }
@@ -847,8 +848,8 @@
 
     Pattern *subPattern = TP->getSubPattern();
     if (coercePatternToType(subPattern, dc, P->getType(),
-                            options|TR_FromNonInferredPattern, &resolver,
-                            TP->getTypeLoc()))
+                            options|TypeResolutionFlags::FromNonInferredPattern,
+                            &resolver, TP->getTypeLoc()))
       hadError = true;
     else {
       TP->setSubPattern(subPattern);
@@ -863,7 +864,7 @@
   case PatternKind::Named:
     // If we're type checking this pattern in a context that can provide type
     // information, then the lack of type information is not an error.
-    if (options & TR_AllowUnspecifiedTypes)
+    if (options & TypeResolutionFlags::AllowUnspecifiedTypes)
       return false;
 
     diagnose(P->getLoc(), diag::cannot_infer_type_for_pattern);
@@ -884,8 +885,8 @@
     // If this is the top level of a function input list, peel off the
     // ImmediateFunctionInput marker and install a FunctionInput one instead.
     auto elementOptions = withoutContext(options);
-    if (options & TR_ImmediateFunctionInput)
-      elementOptions |= TR_FunctionInput;
+    if (options & TypeResolutionFlags::ImmediateFunctionInput)
+      elementOptions |= TypeResolutionFlags::FunctionInput;
 
     bool missingType = false;
     for (unsigned i = 0, e = tuplePat->getNumElements(); i != e; ++i) {
@@ -907,7 +908,8 @@
       P->setType(ErrorType::get(Context));
       return true;
     }
-    if (!missingType && !(options & TR_AllowUnspecifiedTypes)) {
+    if (!missingType && !(options &
+                          TypeResolutionFlags::AllowUnspecifiedTypes)) {
       P->setType(TupleType::get(typeElts, Context));
     }
     return false;
@@ -923,7 +925,7 @@
   case PatternKind::Bool:
   case PatternKind::Expr:
     // In a let/else, these always require an initial value to match against.
-    if (!(options & TR_AllowUnspecifiedTypes)) {
+    if (!(options & TypeResolutionFlags::AllowUnspecifiedTypes)) {
       diagnose(P->getLoc(), diag::refutable_pattern_requires_initializer);
       P->setType(ErrorType::get(Context));
       return true;
@@ -944,7 +946,7 @@
     tyLoc = TypeLoc::withoutLoc(type);
   }
 
-  TypeResolutionOptions subOptions = options - TR_EnumPatternPayload;
+  auto subOptions = options - TypeResolutionFlags::EnumPatternPayload;
   switch (P->getKind()) {
   // For parens and vars, just set the type annotation and propagate inwards.
   case PatternKind::Paren: {
@@ -954,7 +956,7 @@
     // If this is the payload of an enum, and the type is a single-element
     // labeled tuple, treat this as a tuple pattern. It's unlikely that the
     // user is interested in binding a variable of type (foo: Int).
-    if ((options & TR_EnumPatternPayload)
+    if ((options & TypeResolutionFlags::EnumPatternPayload)
         && !isa<TuplePattern>(semantic)) {
       if (auto tupleType = type->getAs<TupleType>()) {
         if (tupleType->getNumElements() == 1
@@ -998,7 +1000,7 @@
     bool hadError = validateTypedPattern(*this, dc, TP, options, resolver);
     if (!hadError) {
       if (!type->isEqual(TP->getType()) && !type->hasError()) {
-        if (options & TR_OverrideType) {
+        if (options & TypeResolutionFlags::OverrideType) {
           TP->setType(type);
         } else {
           diagnose(P->getLoc(), diag::pattern_type_mismatch_context, type);
@@ -1009,7 +1011,7 @@
 
     Pattern *sub = TP->getSubPattern();
     hadError |= coercePatternToType(sub, dc, TP->getType(),
-                                    subOptions | TR_FromNonInferredPattern,
+                       subOptions | TypeResolutionFlags::FromNonInferredPattern,
                                     resolver);
     if (!hadError) {
       TP->setSubPattern(sub);
@@ -1061,9 +1063,9 @@
     }
     
     if (shouldRequireType && 
-        !(options & TR_FromNonInferredPattern) &&
-        !(options & TR_EnumerationVariable) &&
-        !(options & TR_EditorPlaceholder)) {
+        !(options & TypeResolutionFlags::FromNonInferredPattern) &&
+        !(options & TypeResolutionFlags::EnumerationVariable) &&
+        !(options & TypeResolutionFlags::EditorPlaceholder)) {
       diagnose(NP->getLoc(), diag::type_inferred_to_undesirable_type,
                NP->getDecl()->getName(), type, NP->getDecl()->isLet());
       diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence);
@@ -1189,7 +1191,8 @@
     auto IP = cast<IsPattern>(P);
 
     // Type-check the type parameter.
-    if (validateType(IP->getCastTypeLoc(), dc, TR_InExpression))
+    if (validateType(IP->getCastTypeLoc(), dc,
+                     TypeResolutionFlags::InExpression))
       return true;
 
     auto castType = IP->getCastTypeLoc().getType();
@@ -1268,7 +1271,7 @@
     // Coerce the subpattern to the destination type.
     if (Pattern *sub = IP->getSubPattern()) {
       if (coercePatternToType(sub, dc, IP->getCastTypeLoc().getType(),
-                              subOptions|TR_FromNonInferredPattern))
+                        subOptions|TypeResolutionFlags::FromNonInferredPattern))
         return true;
       IP->setSubPattern(sub);
     }
@@ -1398,8 +1401,9 @@
                                               elt, argType);
       else
         elementType = TupleType::getEmpty(Context);
-      if (coercePatternToType(sub, dc, elementType,
-                              subOptions|TR_FromNonInferredPattern|TR_EnumPatternPayload,
+      if (coercePatternToType(sub, dc, elementType, subOptions
+                              | TypeResolutionFlags::FromNonInferredPattern
+                              | TypeResolutionFlags::EnumPatternPayload,
                               resolver))
         return true;
       EEP->setSubPattern(sub);
@@ -1427,8 +1431,9 @@
       Pattern *sub = TuplePattern::createSimple(Context, SourceLoc(),
                                                 elements, SourceLoc(),
                                                 /*implicit*/true);
-      if (coercePatternToType(sub, dc, elementType,
-                              subOptions|TR_FromNonInferredPattern|TR_EnumPatternPayload,
+      if (coercePatternToType(sub, dc, elementType, subOptions
+                              | TypeResolutionFlags::FromNonInferredPattern
+                              | TypeResolutionFlags::EnumPatternPayload,
                               resolver))
         return true;
       EEP->setSubPattern(sub);
@@ -1480,8 +1485,9 @@
     OP->setElementDecl(elementDecl);
 
     Pattern *sub = OP->getSubPattern();
-    if (coercePatternToType(sub, dc, elementType,
-                            subOptions|TR_FromNonInferredPattern|TR_EnumPatternPayload,
+    if (coercePatternToType(sub, dc, elementType, subOptions
+                            | TypeResolutionFlags::FromNonInferredPattern
+                            | TypeResolutionFlags::EnumPatternPayload,
                             resolver))
       return true;
     OP->setSubPattern(sub);
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 7a0f0ee..85f444b 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2266,9 +2266,11 @@
     // Check that T conforms to all inherited protocols.
     for (auto InheritedProto : Proto->getInheritedProtocols()) {
       auto InheritedConformance =
-      TC.conformsToProtocol(T, InheritedProto, DC,
-                            ConformanceCheckFlags::Used,
-                            ComplainLoc);
+      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.
@@ -3558,7 +3560,9 @@
 
   // Check protocol conformances.
   for (auto reqProto : genericSig->getConformsTo(depTy)) {
-    if (!tc.conformsToProtocol(contextType, reqProto, dc, None))
+    if (!tc.conformsToProtocol(
+                          contextType, reqProto, dc,
+                          ConformanceCheckFlags::SkipConditionalRequirements))
       return CheckTypeWitnessResult(reqProto->getDeclaredType());
 
     // FIXME: Why is conformsToProtocol() not enough? The stdlib doesn't
@@ -4659,7 +4663,9 @@
       // If that failed, check whether it's because of the conformance we're
       // evaluating.
       auto localConformance
-        = TC.conformsToProtocol(baseTy, assocType->getProtocol(), DC, None);
+        = TC.conformsToProtocol(
+                          baseTy, assocType->getProtocol(), DC,
+                          ConformanceCheckFlags::SkipConditionalRequirements);
       if (!localConformance || localConformance->isAbstract() ||
           (localConformance->getConcrete()->getRootNormalConformance()
              != Conformance)) {
@@ -4731,12 +4737,11 @@
       SmallVector<Requirement, 4> sanitizedRequirements;
       sanitizeProtocolRequirements(Proto, Proto->getRequirementSignature(),
                                    sanitizedRequirements);
-      auto requirementSig =
-        GenericSignature::get({Proto->getProtocolSelfType()},
-                               sanitizedRequirements);
       auto result =
         TC.checkGenericArguments(DC, SourceLoc(), SourceLoc(),
-                                 typeInContext, requirementSig,
+                                 typeInContext,
+                                 { Proto->getProtocolSelfType() },
+                                 sanitizedRequirements,
                                  QuerySubstitutionMap{substitutions},
                                  TypeChecker::LookUpConformance(
                                    TC, Conformance->getDeclContext()),
@@ -5421,9 +5426,6 @@
   if (!Conformance->getSignatureConformances().empty())
     return;
 
-  auto reqSig = GenericSignature::get({proto->getProtocolSelfType()},
-                                      proto->getRequirementSignature());
-
   auto DC = Conformance->getDeclContext();
   auto substitutingType = DC->mapTypeIntoContext(Conformance->getType());
   auto substitutions = SubstitutionMap::getProtocolSubstitutions(
@@ -5471,10 +5473,11 @@
           concreteConformance->getType()->mapTypeOutOfContext();
 
         conformance = *tc.conformsToProtocol(
-                           interfaceType,
-                           conformance.getRequirement(),
-                           dc,
-                           ConformanceCheckFlags::SuppressDependencyTracking);
+                         interfaceType,
+                         conformance.getRequirement(),
+                         dc,
+                         (ConformanceCheckFlags::SuppressDependencyTracking|
+                          ConformanceCheckFlags::SkipConditionalRequirements));
 
         // Reinstate inherited conformance.
         if (inheritedInterfaceType) {
@@ -5492,7 +5495,9 @@
   auto result = TC.checkGenericArguments(
       DC, Loc, Loc,
       // FIXME: maybe this should be the conformance's type
-      proto->getDeclaredInterfaceType(), reqSig,
+      proto->getDeclaredInterfaceType(),
+      { proto->getProtocolSelfType() },
+      proto->getRequirementSignature(),
       QuerySubstitutionMap{substitutions},
       TypeChecker::LookUpConformance(TC, DC),
       nullptr,
@@ -5919,6 +5924,43 @@
     markConformanceUsed(*lookupResult, DC);
   }
 
+  // If we have a concrete conformance with conditional requirements that
+  // we need to check, do so now.
+  if (lookupResult->isConcrete() &&
+      !lookupResult->getConditionalRequirements().empty() &&
+      !options.contains(ConformanceCheckFlags::SkipConditionalRequirements)) {
+    // Figure out the location of the conditional conformance.
+    auto conformanceDC = lookupResult->getConcrete()->getDeclContext();
+    SourceLoc noteLoc;
+    if (auto ext = dyn_cast<ExtensionDecl>(conformanceDC))
+      noteLoc = ext->getLoc();
+    else
+      noteLoc = cast<NominalTypeDecl>(conformanceDC)->getLoc();
+
+    auto conditionalCheckResult =
+      checkGenericArguments(DC, ComplainLoc, noteLoc, T,
+                            { lookupResult->getRequirement()
+                                ->getProtocolSelfType() },
+                            lookupResult->getConditionalRequirements(),
+                            [](SubstitutableType *dependentType) {
+                              return Type(dependentType);
+                            },
+                            LookUpConformance(*this, DC),
+                            /*unsatisfiedDependency=*/nullptr,
+                            options);
+    switch (conditionalCheckResult) {
+    case RequirementCheckResult::Success:
+      break;
+
+    case RequirementCheckResult::Failure:
+    case RequirementCheckResult::SubstitutionFailure:
+      return None;
+
+    case RequirementCheckResult::UnsatisfiedDependency:
+      llvm_unreachable("Not permissible here");
+    }
+  }
+
   // When requested, print the conformance access path used to find this
   // conformance.
   if (Context.LangOpts.DebugGenericSignatures &&
@@ -6004,11 +6046,13 @@
   if (conformingReplacementType->isTypeParameter())
     return ProtocolConformanceRef(conformedProtocol->getDecl());
 
-  return tc.conformsToProtocol(conformingReplacementType,
-                               conformedProtocol->getDecl(),
-                               dc,
-                               (ConformanceCheckFlags::Used|
-                                ConformanceCheckFlags::InExpression));
+  return tc.conformsToProtocol(
+                         conformingReplacementType,
+                         conformedProtocol->getDecl(),
+                         dc,
+                         (ConformanceCheckFlags::Used|
+                          ConformanceCheckFlags::InExpression|
+                          ConformanceCheckFlags::SkipConditionalRequirements));
 }
 
 /// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
@@ -6053,8 +6097,6 @@
         if (WasUnsatisfied)
           return Action::Stop;
         if (result.getStatus() == RequirementCheckResult::Success)
-          assert(result.getConformance().getConditionalRequirements().empty() &&
-                 "cannot conform conditionally to _ObjectiveCBridgeable");
 
         // Set and Dictionary bridging also requires the conformance
         // of the key type to Hashable.
@@ -6149,9 +6191,6 @@
   auto conformance = conformsToProtocol(type, bridgedStoredNSError, dc,
                                         ConformanceCheckFlags::Used);
   if (conformance && conformance->isConcrete()) {
-    assert(conformance->getConditionalRequirements().empty() &&
-           "cannot conform condtionally to _BridgedStoredNSError");
-
     // Hack: If we've used a conformance to the _BridgedStoredNSError
     // protocol, also use the RawRepresentable and _ErrorCodeProtocol
     // conformances on the Code associated type witness.
@@ -6927,6 +6966,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/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index be4ec40..a24595c 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -555,9 +555,9 @@
   
   Stmt *visitForEachStmt(ForEachStmt *S) {
     TypeResolutionOptions options;
-    options |= TR_AllowUnspecifiedTypes;
-    options |= TR_AllowUnboundGenerics;
-    options |= TR_InExpression;
+    options |= TypeResolutionFlags::AllowUnspecifiedTypes;
+    options |= TypeResolutionFlags::AllowUnboundGenerics;
+    options |= TypeResolutionFlags::InExpression;
     
     if (auto *P = TC.resolvePattern(S->getPattern(), DC,
                                     /*isStmtCondition*/false)) {
@@ -620,9 +620,6 @@
       if (!conformance)
         return nullptr;
 
-      assert(conformance->getConditionalRequirements().empty() &&
-             "conditionally conforming to Sequence is not currently supported");
-
       generatorTy = TC.getWitnessType(sequenceType, sequenceProto,
                                       *conformance,
                                       TC.Context.Id_Iterator,
@@ -859,7 +856,7 @@
           pattern = newPattern;
           // Coerce the pattern to the subject's type.
           if (!subjectType || TC.coercePatternToType(pattern, DC, subjectType,
-                                     TR_InExpression)) {
+                                     TypeResolutionFlags::InExpression)) {
             hadError = true;
 
             // If that failed, mark any variables binding pieces of the pattern
@@ -980,7 +977,8 @@
 
     // Coerce the pattern to the exception type.
     if (!exnType ||
-        coercePatternToType(pattern, DC, exnType, TR_InExpression)) {
+        coercePatternToType(pattern, DC, exnType,
+                            TypeResolutionFlags::InExpression)) {
       // If that failed, be sure to give the variables error types
       // before we type-check the guard.  (This will probably kill
       // most of the type-checking, but maybe not.)
@@ -1557,9 +1555,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/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 7379b5e..28d1106 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -441,7 +441,7 @@
   }
 
   // In SIL mode, Optional<T> interprets T as a SIL type.
-  if (options.contains(TR_SILType)) {
+  if (options.contains(TypeResolutionFlags::SILType)) {
     if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
       if (nominal->classifyAsOptionalType()) {
         // Validate the generic argument.
@@ -459,7 +459,7 @@
   }
 
   // Cannot extend a bound generic type.
-  if (options.contains(TR_ExtensionBinding)) {
+  if (options.contains(TypeResolutionFlags::ExtensionBinding)) {
     diagnose(loc, diag::extension_specialization,
              genericDecl->getName())
       .highlight(generic->getSourceRange());
@@ -504,12 +504,12 @@
     GenericTypeResolver *resolver,
     UnsatisfiedDependency *unsatisfiedDependency) {
 
-  options -= TR_SILType;
-  options -= TR_ImmediateFunctionInput;
-  options -= TR_FunctionInput;
-  options -= TR_TypeAliasUnderlyingType;
-  options -= TR_AllowUnavailableProtocol;
-  options -= TR_AllowIUO;
+  options -= TypeResolutionFlags::SILType;
+  options -= TypeResolutionFlags::ImmediateFunctionInput;
+  options -= TypeResolutionFlags::FunctionInput;
+  options -= TypeResolutionFlags::TypeAliasUnderlyingType;
+  options -= TypeResolutionFlags::AllowUnavailableProtocol;
+  options -= TypeResolutionFlags::AllowIUO;
 
   assert(genericArgs.size() == decl->getGenericParams()->size() &&
          "invalid arguments, use applyGenericArguments for diagnostic emitting");
@@ -599,7 +599,9 @@
   // generic signature.
   if (!hasTypeParameterOrVariable) {
     auto result =
-      checkGenericArguments(dc, loc, noteLoc, unboundType, genericSig,
+      checkGenericArguments(dc, loc, noteLoc, unboundType,
+                            genericSig->getGenericParams(),
+                            genericSig->getRequirements(),
                             QueryTypeSubstitutionMap{subs},
                             LookUpConformance(*this, dc),
                             unsatisfiedDependency);
@@ -685,7 +687,7 @@
   assert(fromDC && "No declaration context for type resolution?");
 
   // Don't validate nominal type declarations during extension binding.
-  if (!options.contains(TR_ExtensionBinding) ||
+  if (!options.contains(TypeResolutionFlags::ExtensionBinding) ||
       !isa<NominalTypeDecl>(typeDecl)) {
     // If we have a callback to report dependencies, do so.
     if (unsatisfiedDependency) {
@@ -713,9 +715,9 @@
                             generic, resolver);
 
   if (type->is<UnboundGenericType>() && !generic &&
-      !options.contains(TR_AllowUnboundGenerics) &&
-      !options.contains(TR_TypeAliasUnderlyingType) &&
-      !options.contains(TR_ResolveStructure)) {
+      !options.contains(TypeResolutionFlags::AllowUnboundGenerics) &&
+      !options.contains(TypeResolutionFlags::TypeAliasUnderlyingType) &&
+      !options.contains(TypeResolutionFlags::ResolveStructure)) {
     diagnoseUnboundGenericType(TC, type, loc);
     return ErrorType::get(TC.Context);
   }
@@ -726,7 +728,7 @@
                                    loc, cast<AssociatedTypeDecl>(typeDecl));
   }
 
-  if (generic && !options.contains(TR_ResolveStructure)) {
+  if (generic && !options.contains(TypeResolutionFlags::ResolveStructure)) {
     // Apply the generic arguments to the type.
     type = TC.applyGenericArguments(type, typeDecl, loc, fromDC, generic,
                                     options, resolver, unsatisfiedDependency);
@@ -824,7 +826,7 @@
 
     // Try ignoring access control.
     DeclContext *lookupDC = dc;
-    if (options.contains(TR_GenericSignature))
+    if (options.contains(TypeResolutionFlags::GenericSignature))
       lookupDC = dc->getParentForLookup();
 
     NameLookupOptions relookupOptions = lookupOptions;
@@ -1088,7 +1090,7 @@
   DeclContext *lookupDC = DC;
 
   // Dynamic 'Self' in the result type of a function body.
-  if (options.contains(TR_DynamicSelfResult) &&
+  if (options.contains(TypeResolutionFlags::DynamicSelfResult) &&
       comp->getIdentifier() == TC.Context.Id_Self) {
     auto func = cast<FuncDecl>(DC);
     assert(func->hasDynamicSelf() && "Not marked as having dynamic Self?");
@@ -1104,7 +1106,7 @@
 
   // For lookups within the generic signature, look at the generic
   // parameters (only), then move up to the enclosing context.
-  if (options.contains(TR_GenericSignature)) {
+  if (options.contains(TypeResolutionFlags::GenericSignature)) {
     Type type = resolveGenericSignatureComponent(
       TC, DC, comp, options, diagnoseErrors, resolver,
       unsatisfiedDependency);
@@ -1112,7 +1114,7 @@
       return type;
 
     if (!DC->isCascadingContextForLookup(/*excludeFunctions*/false))
-      options |= TR_KnownNonCascadingDependency;
+      options |= TypeResolutionFlags::KnownNonCascadingDependency;
 
     lookupDC = DC->getParentForLookup();
   }
@@ -1132,12 +1134,12 @@
   // ImplicitlyUnwrappedOptional where it is not allowed, treat it as
   // if it was spelled Optional.
   if (id == TC.Context.Id_ImplicitlyUnwrappedOptional
-      && !options.contains(TR_AllowIUO)
+      && !options.contains(TypeResolutionFlags::AllowIUO)
       && !TC.Context.isSwiftVersionAtLeast(5))
     id = TC.Context.Id_Optional;
 
   NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
-  if (options.contains(TR_KnownNonCascadingDependency))
+  if (options.contains(TypeResolutionFlags::KnownNonCascadingDependency))
     lookupOptions |= NameLookupFlags::KnownPrivate;
   auto globals = TC.lookupUnqualifiedType(lookupDC,
                                           id,
@@ -1205,7 +1207,7 @@
 
   // Emit diagnostics related to ImplicitlyUnwrappedOptional.
   if (comp->getIdentifier() == TC.Context.Id_ImplicitlyUnwrappedOptional) {
-    if (options.contains(TR_AllowIUO)) {
+    if (options.contains(TypeResolutionFlags::AllowIUO)) {
       if (isa<GenericIdentTypeRepr>(comp)) {
         auto *genericTyR = cast<GenericIdentTypeRepr>(comp);
         assert(genericTyR->getGenericArgs().size() == 1);
@@ -1317,7 +1319,7 @@
 
     // Only the last component of the underlying type of a type alias may
     // be an unbound generic.
-    if (options & TR_TypeAliasUnderlyingType) {
+    if (options & TypeResolutionFlags::TypeAliasUnderlyingType) {
       if (parentTy->is<UnboundGenericType>()) {
         if (diagnoseErrors)
           diagnoseUnboundGenericType(TC, parentTy, parentRange.End);
@@ -1349,9 +1351,9 @@
     }
 
     if (memberType->is<UnboundGenericType>() &&
-        !options.contains(TR_AllowUnboundGenerics) &&
-        !options.contains(TR_TypeAliasUnderlyingType) &&
-        !options.contains(TR_ResolveStructure)) {
+        !options.contains(TypeResolutionFlags::AllowUnboundGenerics) &&
+        !options.contains(TypeResolutionFlags::TypeAliasUnderlyingType) &&
+        !options.contains(TypeResolutionFlags::ResolveStructure)) {
       diagnoseUnboundGenericType(TC, memberType, comp->getLoc());
       return ErrorType::get(TC.Context);
     }
@@ -1381,8 +1383,8 @@
   // Phase 1: Find and bind the component decl.
 
   // Look for member types with the given name.
-  bool isKnownNonCascading = options.contains(TR_KnownNonCascadingDependency);
-  if (!isKnownNonCascading && options.contains(TR_InExpression)) {
+  bool isKnownNonCascading = options.contains(TypeResolutionFlags::KnownNonCascadingDependency);
+  if (!isKnownNonCascading && options.contains(TypeResolutionFlags::InExpression)) {
     // Expressions cannot affect a function's signature.
     isKnownNonCascading = isa<AbstractFunctionDecl>(DC);
   }
@@ -1407,9 +1409,9 @@
   NameLookupOptions lookupOptions = defaultMemberLookupOptions;
   if (isKnownNonCascading)
     lookupOptions |= NameLookupFlags::KnownPrivate;
-  // FIXME: Lift the restriction for TR_InheritanceClause
-  if (options.contains(TR_ExtensionBinding) ||
-      options.contains(TR_InheritanceClause))
+  // FIXME: Lift the restriction for TypeResolutionFlags::InheritanceClause
+  if (options.contains(TypeResolutionFlags::ExtensionBinding) ||
+      options.contains(TypeResolutionFlags::InheritanceClause))
     lookupOptions -= NameLookupFlags::ProtocolMembers;
   LookupTypeResult memberTypes;
   if (parentTy->mayHaveMembers())
@@ -1517,8 +1519,8 @@
                                         TypeResolutionOptions options) {
   // Remember whether this is a function parameter.
   bool isFunctionParam =
-    options.contains(TR_FunctionInput) ||
-    options.contains(TR_ImmediateFunctionInput);
+    options.contains(TypeResolutionFlags::FunctionInput) ||
+    options.contains(TypeResolutionFlags::ImmediateFunctionInput);
 
   bool defaultNoEscape = isFunctionParam;
 
@@ -1585,9 +1587,9 @@
   // To support this, inside inheritance clauses we allow references to
   // protocols that are unavailable in the current type refinement context.
 
-  if (!(options & TR_AllowUnavailable) &&
+  if (!(options & TypeResolutionFlags::AllowUnavailable) &&
       diagnoseAvailability(IdType, DC, *this,
-                           options.contains(TR_AllowUnavailableProtocol))) {
+             options.contains(TypeResolutionFlags::AllowUnavailableProtocol))) {
     Components.back()->setInvalid();
     return ErrorType::get(Context);
   }
@@ -1620,7 +1622,8 @@
       type = ErrorType::get(Context);
 
       // Diagnose types that are illegal in SIL.
-    } else if (options.contains(TR_SILType) && !type->isLegalSILType()) {
+    } else if (options.contains(TypeResolutionFlags::SILType)
+               && !type->isLegalSILType()) {
       diagnose(Loc.getLoc(), diag::illegal_sil_type, type);
       Loc.setType(ErrorType::get(Context), true);
       return true;
@@ -1753,13 +1756,13 @@
       !isa<AttributedTypeRepr>(repr) &&
       !isa<FunctionTypeRepr>(repr) &&
       !isa<IdentTypeRepr>(repr)) {
-    options -= TR_ImmediateFunctionInput;
-    options -= TR_FunctionInput;
-    options -= TR_TypeAliasUnderlyingType;
+    options -= TypeResolutionFlags::ImmediateFunctionInput;
+    options -= TypeResolutionFlags::FunctionInput;
+    options -= TypeResolutionFlags::TypeAliasUnderlyingType;
   }
 
   if (Context.LangOpts.DisableAvailabilityChecking)
-    options |= TR_AllowUnavailable;
+    options |= TypeResolutionFlags::AllowUnavailable;
 
   switch (repr->getKind()) {
   case TypeReprKind::Error:
@@ -1779,7 +1782,7 @@
                                     UnsatisfiedDependency);
 
   case TypeReprKind::Function: {
-    if (!(options & TR_SILType)) {
+    if (!(options & TypeResolutionFlags::SILType)) {
       // Default non-escaping for closure parameters
       auto result =
           resolveASTFunctionType(cast<FunctionTypeRepr>(repr), options);
@@ -1790,7 +1793,7 @@
     return resolveSILFunctionType(cast<FunctionTypeRepr>(repr), options);
   }
   case TypeReprKind::SILBox:
-    assert((options & TR_SILType) && "SILBox repr in non-SIL type context?!");
+    assert((options & TypeResolutionFlags::SILType) && "SILBox repr in non-SIL type context?!");
     return resolveSILBoxType(cast<SILBoxTypeRepr>(repr), options);
 
   case TypeReprKind::Array:
@@ -1861,10 +1864,10 @@
 
   // Remember whether this is a function parameter.
   bool isFunctionParam =
-    options.contains(TR_FunctionInput) ||
-    options.contains(TR_ImmediateFunctionInput);
+    options.contains(TypeResolutionFlags::FunctionInput) ||
+    options.contains(TypeResolutionFlags::ImmediateFunctionInput);
   bool isVariadicFunctionParam =
-    options.contains(TR_VariadicFunctionInput);
+    options.contains(TypeResolutionFlags::VariadicFunctionInput);
 
   // The type we're working with, in case we want to build it differently
   // based on the attributes we see.
@@ -1889,10 +1892,10 @@
           Optional<MetatypeRepresentation> storedRepr;
           // The instance type is not a SIL type.
           auto instanceOptions = options;
-          instanceOptions -= TR_SILType;
-          instanceOptions -= TR_ImmediateFunctionInput;
-          instanceOptions -= TR_FunctionInput;
-          instanceOptions -= TR_TypeAliasUnderlyingType;
+          instanceOptions -= TypeResolutionFlags::SILType;
+          instanceOptions -= TypeResolutionFlags::ImmediateFunctionInput;
+          instanceOptions -= TypeResolutionFlags::FunctionInput;
+          instanceOptions -= TypeResolutionFlags::TypeAliasUnderlyingType;
 
           auto instanceTy = resolveType(base, instanceOptions);
           if (!instanceTy || instanceTy->hasError())
@@ -1954,7 +1957,7 @@
   
   // Some function representation attributes are not supported at source level;
   // only SIL knows how to handle them.  Reject them unless this is a SIL input.
-  if (!(options & TR_SILType)) {
+  if (!(options & TypeResolutionFlags::SILType)) {
     for (auto silOnlyAttr : {TAK_callee_owned, TAK_callee_guaranteed}) {
       checkUnsupportedAttr(silOnlyAttr);
     }
@@ -1986,7 +1989,7 @@
       attrs.clearAttribute(TAK_autoclosure);
     }
     // Fall through to diagnose below.
-  } else if (hasFunctionAttr && (options & TR_SILType)) {
+  } else if (hasFunctionAttr && (options & TypeResolutionFlags::SILType)) {
     SILFunctionType::Representation rep;
     TypeRepr *witnessMethodProtocol = nullptr;
 
@@ -2107,9 +2110,9 @@
   }
 
   auto instanceOptions = options;
-  instanceOptions -= TR_ImmediateFunctionInput;
-  instanceOptions -= TR_FunctionInput;
-  instanceOptions -= TR_TypeAliasUnderlyingType;
+  instanceOptions -= TypeResolutionFlags::ImmediateFunctionInput;
+  instanceOptions -= TypeResolutionFlags::FunctionInput;
+  instanceOptions -= TypeResolutionFlags::TypeAliasUnderlyingType;
 
   // If we didn't build the type differently above, we might have
   // a typealias pointing at a function type with the @escaping
@@ -2135,7 +2138,7 @@
             .fixItRemove(attrRange);
 
         // Try to find a helpful note based on how the type is being used
-        if (options.contains(TR_ImmediateOptionalTypeArgument)) {
+        if (options.contains(TypeResolutionFlags::ImmediateOptionalTypeArgument)) {
           TC.diagnose(repr->getLoc(), diag::escaping_optional_type_argument);
         }
       }
@@ -2206,19 +2209,19 @@
   }
   
   // In SIL *only*, allow @block_storage to specify a block storage type.
-  if ((options & TR_SILType) && attrs.has(TAK_block_storage)) {
+  if ((options & TypeResolutionFlags::SILType) && attrs.has(TAK_block_storage)) {
     ty = SILBlockStorageType::get(ty->getCanonicalType());
     attrs.clearAttribute(TAK_block_storage);
   }
   
   // In SIL *only*, allow @box to specify a box type.
-  if ((options & TR_SILType) && attrs.has(TAK_box)) {
+  if ((options & TypeResolutionFlags::SILType) && attrs.has(TAK_box)) {
     ty = SILBoxType::get(ty->getCanonicalType());
     attrs.clearAttribute(TAK_box);
   }
 
   // In SIL *only*, allow @dynamic_self to specify a dynamic Self type.
-  if ((options & TR_SILMode) && attrs.has(TAK_dynamic_self)) {
+  if ((options & TypeResolutionFlags::SILMode) && attrs.has(TAK_dynamic_self)) {
     ty = rebuildWithDynamicSelf(TC.Context, ty);
     attrs.clearAttribute(TAK_dynamic_self);
   }
@@ -2234,17 +2237,17 @@
 Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
                                           TypeResolutionOptions options,
                                           FunctionType::ExtInfo extInfo) {
-  options -= TR_ImmediateFunctionInput;
-  options -= TR_FunctionInput;
-  options -= TR_TypeAliasUnderlyingType;
+  options -= TypeResolutionFlags::ImmediateFunctionInput;
+  options -= TypeResolutionFlags::FunctionInput;
+  options -= TypeResolutionFlags::TypeAliasUnderlyingType;
   // FIXME: Until we remove the IUO type from the type system, we
   // need to continue to parse IUOs in SIL tests so that we can
   // match the types we generate from the importer.
-  if (!options.contains(TR_SILMode))
-    options -= TR_AllowIUO;
+  if (!options.contains(TypeResolutionFlags::SILMode))
+    options -= TypeResolutionFlags::AllowIUO;
 
   Type inputTy = resolveType(repr->getArgsTypeRepr(),
-                             options | TR_ImmediateFunctionInput);
+                         options | TypeResolutionFlags::ImmediateFunctionInput);
   if (!inputTy || inputTy->hasError()) return inputTy;
 
   Type outputTy = resolveType(repr->getResultTypeRepr(), options);
@@ -2413,9 +2416,9 @@
                                           SILFunctionType::ExtInfo extInfo,
                                           ParameterConvention callee,
                                           TypeRepr *witnessMethodProtocol) {
-  options -= TR_ImmediateFunctionInput;
-  options -= TR_FunctionInput;
-  options -= TR_TypeAliasUnderlyingType;
+  options -= TypeResolutionFlags::ImmediateFunctionInput;
+  options -= TypeResolutionFlags::FunctionInput;
+  options -= TypeResolutionFlags::TypeAliasUnderlyingType;
 
   bool hasError = false;
 
@@ -2452,7 +2455,7 @@
 
       for (auto elt : tuple->getElements()) {
         auto param = resolveSILParameter(elt.Type,
-                                         options | TR_ImmediateFunctionInput);
+                         options | TypeResolutionFlags::ImmediateFunctionInput);
         params.push_back(param);
         if (!param.getType()) return nullptr;
 
@@ -2461,7 +2464,7 @@
       }
     } else {
       SILParameterInfo param = resolveSILParameter(repr->getArgsTypeRepr(),
-                                           options | TR_ImmediateFunctionInput);
+                         options | TypeResolutionFlags::ImmediateFunctionInput);
       params.push_back(param);
       if (!param.getType()) return nullptr;
 
@@ -2565,14 +2568,16 @@
                                            TypeResolutionOptions options) {
   AttributedTypeRepr attrRepr(attrs, repr);
   SILParameterInfo paramInfo =
-    resolveSILParameter(&attrRepr, options | TR_ImmediateFunctionInput);
+    resolveSILParameter(&attrRepr, options |
+                                   TypeResolutionFlags::ImmediateFunctionInput);
   return SILYieldInfo(paramInfo.getType(), paramInfo.getConvention());
 }
 
 SILParameterInfo TypeResolver::resolveSILParameter(
                                  TypeRepr *repr,
                                  TypeResolutionOptions options) {
-  assert((options & TR_FunctionInput) | (options & TR_ImmediateFunctionInput) &&
+  assert((options & TypeResolutionFlags::FunctionInput)
+         | (options & TypeResolutionFlags::ImmediateFunctionInput) &&
          "Parameters should be marked as inputs");
   auto convention = DefaultParameterConvention;
   Type type;
@@ -2738,13 +2743,13 @@
 Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
                                             TypeResolutionOptions options) {
   // inout is only valid for (non-subscript) function parameters.
-  if ((options & TR_SubscriptParameters) ||
-        (!(options & TR_FunctionInput) &&
-         !(options & TR_ImmediateFunctionInput))) {
+  if ((options & TypeResolutionFlags::SubscriptParameters) ||
+        (!(options & TypeResolutionFlags::FunctionInput) &&
+         !(options & TypeResolutionFlags::ImmediateFunctionInput))) {
     decltype(diag::attr_only_on_parameters) diagID;
-    if (options & TR_SubscriptParameters) {
+    if (options & TypeResolutionFlags::SubscriptParameters) {
       diagID = diag::attr_not_on_subscript_parameters;
-    } else if (options & TR_VariadicFunctionInput) {
+    } else if (options & TypeResolutionFlags::VariadicFunctionInput) {
       diagID = diag::attr_not_on_variadic_parameters;
     } else {
       diagID = diag::attr_only_on_parameters;
@@ -2758,9 +2763,9 @@
   }
 
   // Anything within the inout isn't a parameter anymore.
-  options -= TR_ImmediateFunctionInput;
-  options -= TR_FunctionInput;
-  options -= TR_TypeAliasUnderlyingType;
+  options -= TypeResolutionFlags::ImmediateFunctionInput;
+  options -= TypeResolutionFlags::FunctionInput;
+  options -= TypeResolutionFlags::TypeAliasUnderlyingType;
 
   Type ty = resolveType(repr->getBase(), options);
   if (!ty || ty->hasError()) return ty;
@@ -2824,7 +2829,7 @@
 Type TypeResolver::resolveOptionalType(OptionalTypeRepr *repr,
                                        TypeResolutionOptions options) {
   auto elementOptions = withoutContext(options, true);
-  elementOptions |= TR_ImmediateOptionalTypeArgument;
+  elementOptions |= TypeResolutionFlags::ImmediateOptionalTypeArgument;
 
   // The T in T? is a generic type argument and therefore always an AST type.
   // FIXME: diagnose non-materializability of element type!
@@ -2840,7 +2845,7 @@
 Type TypeResolver::resolveImplicitlyUnwrappedOptionalType(
        ImplicitlyUnwrappedOptionalTypeRepr *repr,
        TypeResolutionOptions options) {
-  if (!options.contains(TR_AllowIUO)) {
+  if (!options.contains(TypeResolutionFlags::AllowIUO)) {
     Diagnostic diag = diag::
         implicitly_unwrapped_optional_in_illegal_position_decay_to_optional;
 
@@ -2852,7 +2857,7 @@
   }
 
   auto elementOptions = withoutContext(options, true);
-  elementOptions |= TR_ImmediateOptionalTypeArgument;
+  elementOptions |= TypeResolutionFlags::ImmediateOptionalTypeArgument;
 
   // The T in T! is a generic type argument and therefore always an AST type.
   // FIXME: diagnose non-materializability of element type!
@@ -2860,7 +2865,7 @@
   if (!baseTy || baseTy->hasError()) return baseTy;
 
   Type uncheckedOptionalTy;
-  if (!options.contains(TR_AllowIUO))
+  if (!options.contains(TypeResolutionFlags::AllowIUO))
     // Treat IUOs in illegal positions as optionals.
     uncheckedOptionalTy = TC.getOptionalType(repr->getExclamationLoc(), baseTy);
   else
@@ -2875,7 +2880,8 @@
 
 Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
                                     TypeResolutionOptions options) {
-  bool isImmediateFunctionInput = options.contains(TR_ImmediateFunctionInput);
+  bool isImmediateFunctionInput = options.contains(
+                                   TypeResolutionFlags::ImmediateFunctionInput);
   SmallVector<TupleTypeElt, 8> elements;
   elements.reserve(repr->getNumElements());
   
@@ -2887,8 +2893,8 @@
     // FIXME: Until we remove the IUO type from the type system, we
     // need to continue to parse IUOs in SIL tests so that we can
     // match the types we generate from the importer.
-    if (!options.contains(TR_SILMode))
-      elementOptions -= TR_AllowIUO;
+    if (!options.contains(TypeResolutionFlags::SILMode))
+      elementOptions -= TypeResolutionFlags::AllowIUO;
 
     // If we have a single ParenType, don't clear the context bits; we
     // still want to parse the type contained therein as if it were in
@@ -2897,13 +2903,13 @@
     // `FunctionInput` so that e.g. ((foo: Int)) -> Int is considered a
     // tuple argument rather than a labeled Int argument.
     if (isImmediateFunctionInput) {
-      elementOptions -= TR_ImmediateFunctionInput;
-      elementOptions |= TR_FunctionInput;
+      elementOptions -= TypeResolutionFlags::ImmediateFunctionInput;
+      elementOptions |= TypeResolutionFlags::FunctionInput;
     }
   } else {
     elementOptions = withoutContext(elementOptions, true);
     if (isImmediateFunctionInput)
-      elementOptions |= TR_FunctionInput;
+      elementOptions |= TypeResolutionFlags::FunctionInput;
   }
 
   bool complained = false;
@@ -2935,7 +2941,7 @@
     if (repr->hasEllipsis() &&
         elements.size() == repr->getEllipsisIndex()) {
       thisElementOptions = withoutContext(elementOptions);
-      thisElementOptions |= TR_VariadicFunctionInput;
+      thisElementOptions |= TypeResolutionFlags::VariadicFunctionInput;
       variadic = true;
     }
 
@@ -2961,8 +2967,8 @@
   // or SIL, either.
   if (!isImmediateFunctionInput) {
     if (elements.size() == 1 && elements[0].hasName()
-        && !(options & TR_SILType)
-        && !(options & TR_EnumCase)) {
+        && !(options & TypeResolutionFlags::SILType)
+        && !(options & TypeResolutionFlags::EnumCase)) {
       if (!complained) {
         TC.diagnose(repr->getElementNameLoc(0),
                     diag::tuple_single_element)
@@ -3156,7 +3162,7 @@
   // In SIL mode, a metatype must have a @thin, @thick, or
   // @objc_metatype attribute, so metatypes should have been lowered
   // in resolveAttributedType.
-  if (options & TR_SILType) {
+  if (options & TypeResolutionFlags::SILType) {
     TC.diagnose(repr->getStartLoc(), diag::sil_metatype_without_repr);
     storedRepr = MetatypeRepresentation::Thick;
   }
@@ -3187,7 +3193,7 @@
   // In SIL mode, a metatype must have a @thin, @thick, or
   // @objc_metatype attribute, so metatypes should have been lowered
   // in resolveAttributedType.
-  if (options & TR_SILType) {
+  if (options & TypeResolutionFlags::SILType) {
     TC.diagnose(repr->getStartLoc(), diag::sil_metatype_without_repr);
     storedRepr = MetatypeRepresentation::Thick;
   }
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 18ffe45..cb30575 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -306,8 +306,8 @@
   // Validate the representation.
   // FIXME: Perform some kind of "shallow" validation here?
   TypeResolutionOptions options;
-  options |= TR_AllowUnboundGenerics;
-  options |= TR_ExtensionBinding;
+  options |= TypeResolutionFlags::AllowUnboundGenerics;
+  options |= TypeResolutionFlags::ExtensionBinding;
   if (TC.validateType(ED->getExtendedTypeLoc(), dc, options)) {
     ED->setInvalid();
     return;
@@ -710,13 +710,13 @@
   TypeResolutionOptions options;
 
   // Fine to have unbound generic types.
-  options |= TR_AllowUnboundGenerics;
+  options |= TypeResolutionFlags::AllowUnboundGenerics;
   if (isSILMode) {
-    options |= TR_SILMode;
-    options |= TR_AllowIUO;
+    options |= TypeResolutionFlags::SILMode;
+    options |= TypeResolutionFlags::AllowIUO;
   }
   if (isSILType)
-    options |= TR_SILType;
+    options |= TypeResolutionFlags::SILType;
 
   GenericTypeToArchetypeResolver contextResolver(GenericEnv);
 
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 0bb7323..83f5354 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -451,114 +451,109 @@
 
 /// Flags that describe the context of type checking a pattern or
 /// type.
-enum TypeResolutionFlags : unsigned {
+enum class TypeResolutionFlags : unsigned {
   /// Whether to allow unspecified types within a pattern.
-  TR_AllowUnspecifiedTypes = 0x01,
+  AllowUnspecifiedTypes = 0x01,
 
   /// Whether the given type can override the type of a typed pattern.
-  TR_OverrideType = 0x04,
+  OverrideType = 0x04,
 
   /// Whether to allow unbound generic types.
-  TR_AllowUnboundGenerics = 0x08,
+  AllowUnboundGenerics = 0x08,
 
   /// Whether we are validating the type for SIL.
-  TR_SILType = 0x10,
+  SILType = 0x10,
 
-  /// Whether we are parsing a SIL file.  Not the same as TR_SILType,
+  /// Whether we are parsing a SIL file.  Not the same as SILType,
   /// because the latter is not set if we're parsing an AST type.
-  TR_SILMode = 0x20,
+  SILMode = 0x20,
 
   /// Whether we are in the input type of a function, or under one level of
   /// tuple type.  This is not set for multi-level tuple arguments.
-  TR_FunctionInput = 0x40,
+  FunctionInput = 0x40,
 
   /// Whether this is the immediate input type to a function type,
-  TR_ImmediateFunctionInput = 0x80,
+  ImmediateFunctionInput = 0x80,
 
   /// Whether this is a variadic function input.
-  TR_VariadicFunctionInput = 0x100,
+  VariadicFunctionInput = 0x100,
 
   /// Whether we are in the result type of a function body that is
   /// known to produce dynamic Self.
-  TR_DynamicSelfResult = 0x200,
+  DynamicSelfResult = 0x200,
 
   /// Whether this is a resolution based on a non-inferred type pattern.
-  TR_FromNonInferredPattern = 0x400,
+  FromNonInferredPattern = 0x400,
 
   /// Whether we are the variable type in a for/in statement.
-  TR_EnumerationVariable = 0x800,
+  EnumerationVariable = 0x800,
 
   /// Whether we are looking only in the generic signature of the context
   /// we're searching, rather than the entire context.
-  TR_GenericSignature = 0x1000,
+  GenericSignature = 0x1000,
 
   /// Whether an unavailable protocol can be referenced.
-  TR_AllowUnavailableProtocol = 0x2000,
+  AllowUnavailableProtocol = 0x2000,
 
   /// Whether this type is the value carried in an enum case.
-  TR_EnumCase = 0x4000,
+  EnumCase = 0x4000,
 
   /// Whether this type is being used in an expression or local declaration.
   ///
   /// This affects what sort of dependencies are recorded when resolving the
   /// type.
-  TR_InExpression = 0x8000,
+  InExpression = 0x8000,
 
   /// Whether this type resolution is guaranteed not to affect downstream files.
-  TR_KnownNonCascadingDependency = 0x10000,
+  KnownNonCascadingDependency = 0x10000,
 
   /// Whether we should allow references to unavailable types.
-  TR_AllowUnavailable = 0x20000,
+  AllowUnavailable = 0x20000,
 
   /// Whether this is the payload subpattern of an enum pattern.
-  TR_EnumPatternPayload = 0x40000,
+  EnumPatternPayload = 0x40000,
 
   /// Whether we are binding an extension declaration, which limits
   /// the lookup.
-  TR_ExtensionBinding = 0x80000,
+  ExtensionBinding = 0x80000,
 
   /// Whether we are in the inheritance clause of a nominal type declaration
   /// or extension.
-  TR_InheritanceClause = 0x100000,
+  InheritanceClause = 0x100000,
 
   /// Whether we should resolve only the structure of the resulting
   /// type rather than its complete semantic properties.
-  TR_ResolveStructure = 0x200000,
+  ResolveStructure = 0x200000,
 
   /// Whether this is the type of an editor placeholder.
-  TR_EditorPlaceholder = 0x400000,
+  EditorPlaceholder = 0x400000,
 
   /// Whether we are in a type argument for an optional
-  TR_ImmediateOptionalTypeArgument = 0x800000,
+  ImmediateOptionalTypeArgument = 0x800000,
 
   /// Whether we are checking the underlying type of a typealias.
-  TR_TypeAliasUnderlyingType = 0x1000000,
+  TypeAliasUnderlyingType = 0x1000000,
 
   /// Whether we are checking the parameter list of a subscript.
-  TR_SubscriptParameters = 0x2000000,
+  SubscriptParameters = 0x2000000,
 
   /// Is it okay to resolve an IUO sigil ("!") here?
-  TR_AllowIUO = 0x4000000,
+  AllowIUO = 0x4000000,
 };
 
 /// Option set describing how type resolution should work.
 typedef OptionSet<TypeResolutionFlags> TypeResolutionOptions;
 
-inline TypeResolutionOptions operator|(TypeResolutionFlags lhs,
-                                       TypeResolutionFlags rhs) {
-  return TypeResolutionOptions(lhs) | rhs;
-}
-
 /// Strip the contextual options from the given type resolution options.
 static inline TypeResolutionOptions
 withoutContext(TypeResolutionOptions options, bool preserveSIL = false) {
-  options -= TR_ImmediateFunctionInput;
-  options -= TR_FunctionInput;
-  options -= TR_VariadicFunctionInput;
-  options -= TR_EnumCase;
-  options -= TR_ImmediateOptionalTypeArgument;
-  options -= TR_AllowIUO;
-  if (!preserveSIL) options -= TR_SILType;
+  options -= TypeResolutionFlags::ImmediateFunctionInput;
+  options -= TypeResolutionFlags::FunctionInput;
+  options -= TypeResolutionFlags::VariadicFunctionInput;
+  options -= TypeResolutionFlags::EnumCase;
+  options -= TypeResolutionFlags::ImmediateOptionalTypeArgument;
+  options -= TypeResolutionFlags::AllowIUO;
+  if (!preserveSIL) options -= TypeResolutionFlags::SILType;
   return options;
 }
 
@@ -669,6 +664,13 @@
   /// FIXME: This deals with some oddities with the
   /// _ObjectiveCBridgeable conformances.
   SuppressDependencyTracking = 0x04,
+  /// Whether to skip the check for any conditional conformances.
+  ///
+  /// When set, the caller takes responsibility for any
+  /// conditional requirements required for the conformance to be
+  /// correctly used. Otherwise (the default), all of the conditional
+  /// requirements will be checked.
+  SkipConditionalRequirements = 0x08,
 };
 
 /// Options that control protocol conformance checking.
@@ -1461,6 +1463,24 @@
                             GenericTypeResolver *resolver,
                             GenericSignatureBuilder *builder = nullptr);
 
+  /// Create a text string that describes the bindings of generic parameters
+  /// that are relevant to the given set of types, e.g.,
+  /// "[with T = Bar, U = Wibble]".
+  ///
+  /// \param types The types that will be scanned for generic type parameters,
+  /// which will be used in the resulting type.
+  ///
+  /// \param genericParams The generic parameters to use to resugar any
+  /// generic parameters that occur within the types.
+  ///
+  /// \param substitutions The generic parameter -> generic argument
+  /// substitutions that will have been applied to these types.
+  /// These are used to produce the "parameter = argument" bindings in the test.
+  static std::string
+  gatherGenericParamBindingsText(ArrayRef<Type> types,
+                                 ArrayRef<GenericTypeParamType *> genericParams,
+                                 TypeSubstitutionFn substitutions);
+
   /// Check the given set of generic arguments against the requirements in a
   /// generic signature.
   ///
@@ -1468,7 +1488,9 @@
   /// \param loc The location at which any diagnostics should be emitted.
   /// \param noteLoc The location at which any notes will be printed.
   /// \param owner The type that owns the generic signature.
-  /// \param genericSig The actual generic signature.
+  /// \param genericParams The generic parameters being substituted.
+  /// \param requirements The requirements against which the generic arguments
+  /// should be checked.
   /// \param substitutions Substitutions from interface types of the signature.
   /// \param unsatisfiedDependency Optional callback for reporting unsatisfied
   /// dependencies.
@@ -1478,7 +1500,9 @@
   /// notify callers about diagnosed errors.
   RequirementCheckResult checkGenericArguments(
       DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner,
-      GenericSignature *genericSig, TypeSubstitutionFn substitutions,
+      ArrayRef<GenericTypeParamType *> genericParams,
+      ArrayRef<Requirement> requirements,
+      TypeSubstitutionFn substitutions,
       LookupConformanceFn conformances,
       UnsatisfiedDependency *unsatisfiedDependency,
       ConformanceCheckOptions conformanceOptions = ConformanceCheckFlags::Used,
@@ -2267,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
   ///
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/SwiftDemangle/CMakeLists.txt b/lib/SwiftDemangle/CMakeLists.txt
index 8a89845..417aaa2 100644
--- a/lib/SwiftDemangle/CMakeLists.txt
+++ b/lib/SwiftDemangle/CMakeLists.txt
@@ -3,11 +3,6 @@
   MangleHack.cpp
   LINK_LIBRARIES swiftDemangling)
 
-# We don't need to link against libbsd on MacOS and FreeBSD.
-if (NOT APPLE AND (NOT SWIFT_HOST_VARIANT STREQUAL "freebsd"))
-  target_link_libraries(swiftDemangle PRIVATE bsd)
-endif()
-
 swift_install_in_component(compiler
     TARGETS swiftDemangle
     LIBRARY DESTINATION "lib${LLVM_LIBDIR_SUFFIX}"
diff --git a/lib/SwiftDemangle/SwiftDemangle.cpp b/lib/SwiftDemangle/SwiftDemangle.cpp
index 75029b7..9069aa6 100644
--- a/lib/SwiftDemangle/SwiftDemangle.cpp
+++ b/lib/SwiftDemangle/SwiftDemangle.cpp
@@ -17,9 +17,6 @@
 
 #include "swift/Demangling/Demangle.h"
 #include "swift/SwiftDemangle/SwiftDemangle.h"
-#if defined(__linux__) || defined(_WIN32)
-#include <bsd/string.h>
-#endif
 
 static size_t swift_demangle_getDemangledName_Options(const char *MangledName,
     char *OutputBuffer, size_t Length,
@@ -36,8 +33,12 @@
   if (Result == MangledName)
     return 0; // Not a mangled name
 
-  // Copy the result to an output buffer.
-  return strlcpy(OutputBuffer, Result.c_str(), Length);
+  // Copy the result to an output buffer and ensure '\0' termination.
+  if (OutputBuffer && Length > 0) {
+    auto Dest = strncpy(OutputBuffer, Result.c_str(), Length);
+    Dest[Length - 1] = '\0';
+  }
+  return Result.length();
 }
 
 size_t swift_demangle_getDemangledName(const char *MangledName,
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..1f4b3e7 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -73,10 +73,12 @@
 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.");
@@ -304,23 +306,23 @@
 }
 
 GenericParameterSyntax
-SyntaxFactory::makeGenericParameter(TypeIdentifierSyntax Type,
+SyntaxFactory::makeGenericParameter(TokenSyntax Name,
   llvm::Optional<TokenSyntax> TrailingComma) {
-  return makeGenericParameter(Type, None, None, TrailingComma);
+  return makeGenericParameter(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 48367e9..1afdb90 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -10,331 +10,115 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "swift/Syntax/SyntaxParsingContext.h"
 #include "swift/AST/Module.h"
 #include "swift/Basic/Defer.h"
-#include "swift/Parse/Token.h"
 #include "swift/Parse/Parser.h"
-#include "swift/Syntax/RawTokenSyntax.h"
-#include "swift/Syntax/TokenSyntax.h"
-#include "swift/Syntax/References.h"
+#include "swift/Parse/Token.h"
 #include "swift/Syntax/RawSyntax.h"
+#include "swift/Syntax/RawTokenSyntax.h"
+#include "swift/Syntax/References.h"
 #include "swift/Syntax/Syntax.h"
-#include "swift/Syntax/TokenKinds.h"
-#include "swift/Syntax/Trivia.h"
-#include "swift/Syntax/SyntaxParsingContext.h"
 #include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenKinds.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/Trivia.h"
 
 using namespace swift;
 using namespace swift::syntax;
 
 namespace {
-static Syntax makeUnknownSyntax(SyntaxKind Kind, ArrayRef<Syntax> SubExpr) {
+static RC<RawSyntax> makeUnknownSyntax(SyntaxKind Kind,
+                                       ArrayRef<RC<RawSyntax>> Parts) {
   assert(isUnknownKind(Kind));
-  RawSyntax::LayoutList Layout;
-  std::transform(SubExpr.begin(), SubExpr.end(), std::back_inserter(Layout),
-                 [](const Syntax &S) { return S.getRaw(); });
-  return make<Syntax>(RawSyntax::make(Kind, Layout, SourcePresence::Present));
+  RawSyntax::LayoutList Layout(Parts);
+  return RawSyntax::make(Kind, Layout, SourcePresence::Present);
 }
 
-static ArrayRef<Syntax> getSyntaxNodes(ArrayRef<RawSyntaxInfo> RawNodes,
-                                       llvm::SmallVectorImpl<Syntax> &Scratch) {
-  std::transform(RawNodes.begin(), RawNodes.end(), std::back_inserter(Scratch),
-    [](const RawSyntaxInfo &Info) { return Info.makeSyntax<Syntax>(); });
-  return Scratch;
-}
-
-static SourceRange getNodesRange(ArrayRef<RawSyntaxInfo> RawNodes) {
-  SourceLoc StartLoc, EndLoc;
-  for (auto Info: RawNodes) {
-    if (Info.isImplicit())
-      continue;
-    if (StartLoc.isInvalid()) {
-      StartLoc = Info.getStartLoc();
-    }
-    EndLoc = Info.getEndLoc();
-  }
-  assert(StartLoc.isValid() == EndLoc.isValid());
-  return SourceRange(StartLoc, EndLoc);
-}
-
-static RawSyntaxInfo createSyntaxAs(ArrayRef<RawSyntaxInfo> Parts,
-                                    SyntaxKind Kind) {
+static RC<RawSyntax> createSyntaxAs(SyntaxKind Kind,
+                                    ArrayRef<RC<RawSyntax>> Parts) {
+  // Convert RawSyntax to Syntax for SyntaxFactory.
   llvm::SmallVector<Syntax, 8> Scratch;
-  auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+  std::transform(Parts.begin(), Parts.end(), std::back_inserter(Scratch),
+                 [](const RC<RawSyntax> &Raw) { return make<Syntax>(Raw); });
 
   // Try to create the node of the given syntax.
-  Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
-  if (!Result) {
+  if (auto Node = SyntaxFactory::createSyntax(Kind, Scratch))
+    return Node->getRaw();
 
-    // If unable to create, we should create an unknown node.
-    Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
-                                     SyntaxParts));
-  }
-  return { getNodesRange(Parts), Result->getRaw() };
+  // Fallback to unknown syntax for the category.
+  return makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind), Parts);
 }
+
 } // End of anonymous namespace
 
-struct SyntaxParsingContext::ContextInfo {
-  bool Enabled;
-private:
-  SourceLoc ContextStartLoc;
-  std::vector<RawSyntaxInfo> PendingSyntax;
-
-  // All tokens after the start of this context.
-  ArrayRef<RawSyntaxInfo> Tokens;
-
-  ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) const {
-    for (auto It = Tokens.begin(); It != Tokens.end(); It ++) {
-      assert(It->getStartLoc() == It->getEndLoc());
-      if (It->getStartLoc() == Loc)
-        return It;
-    }
-    llvm_unreachable("cannot find the token on the given location");
-  }
-
-public:
-  ContextInfo(SourceFile &File, unsigned BufferID):
-      Enabled(File.shouldKeepSyntaxInfo()) {
-    if (Enabled) {
-      populateTokenSyntaxMap(File.getASTContext().LangOpts,
-                             File.getASTContext().SourceMgr,
-                             BufferID, File.AllRawTokenSyntax);
-      Tokens = File.AllRawTokenSyntax;
-      assert(Tokens.back().makeSyntax<TokenSyntax>().getTokenKind() == tok::eof);
-    }
-  }
-
-  ContextInfo(ArrayRef<RawSyntaxInfo> Tokens, bool Enabled): Enabled(Enabled) {
-    if (Enabled) {
-      this->Tokens = Tokens;
-    }
-  }
-
-  // Squash N syntax nodex from the back of the pending list into one.
-  void createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
-                               unsigned N);
-  void createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse);
-  std::vector<RawSyntaxInfo> collectAllSyntax(SourceLoc EndLoc);
-  ArrayRef<RawSyntaxInfo> allTokens() const { return Tokens; }
-  ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; }
-  SourceLoc getContextStartLoc() const { return ContextStartLoc; }
-
-  void addPendingSyntax(RawSyntaxInfo Info) {
-    assert(Info.isImplicit() || PendingSyntax.empty() ||
-           PendingSyntax.back().getStartLoc().getOpaquePointerValue() <
-             Info.getStartLoc().getOpaquePointerValue());
-    assert(!Info.RawNode->isToken() && "Pending syntax should not have tokens");
-    PendingSyntax.push_back(Info);
-  }
-
-  void setContextStart(SourceLoc Loc) {
-    assert(ContextStartLoc.isInvalid());
-    ContextStartLoc = Loc;
-    Tokens = Tokens.slice(findTokenAt(Loc) - Tokens.begin());
-  }
-
-  ArrayRef<RawSyntaxInfo> dropTokenAt(SourceLoc Loc) const {
-    return Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
-  }
-
-  // Check if the pending syntax is a token syntax in the given kind.
-  bool checkTokenFromBack(tok Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
-                          unsigned OffsetFromBack = 0) {
-    if (UsedTokens.size() - 1 < OffsetFromBack)
-      return false;
-    auto Back = UsedTokens[UsedTokens.size() - 1 - OffsetFromBack].
-      makeSyntax<Syntax>().getAs<TokenSyntax>();
-    return Back.hasValue() && Back->getTokenKind() == Kind;
-  }
-};
-
-static void addNodeToResults(std::vector<RawSyntaxInfo> &Results,
-                             std::vector<RawSyntaxInfo> &ImplicitNodes,
-                             RawSyntaxInfo Info) {
-  // Add implicit nodes before adding the explicit nodes they attach to.
-  assert(!Info.isImplicit());
-  auto StartSize = Results.size();
-
-  // Find all implicit nodes where the attach-to location is the start position
-  // of this non-implicit nodes.
-  Results.insert(Results.end(),
-                 std::find_if(ImplicitNodes.begin(), ImplicitNodes.end(),
-                   [&](const RawSyntaxInfo &Imp) {
-                     return Imp.BeforeLoc == Info.getStartLoc();
-                   }),
-                 ImplicitNodes.end());
-
-  // If any implicit nodes are inserted to results, we should clear the buffer
-  // to avoid re-inserting them.
-  if (StartSize != Results.size()) {
-    ImplicitNodes.clear();
-  }
-
-  // Add the non-implicit node.
-  Results.emplace_back(Info);
+SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder,
+                                           SourceFile &SF)
+    : Parent(nullptr), CtxtHolder(CtxtHolder), Mode(AccumulationMode::Root),
+      SF(&SF), Enabled(SF.shouldKeepSyntaxInfo()) {
+  CtxtHolder = this;
 }
 
-std::vector<RawSyntaxInfo>
-SyntaxParsingContext::ContextInfo::collectAllSyntax(SourceLoc EndLoc) {
-  std::vector<RawSyntaxInfo> Results;
-  std::vector<RawSyntaxInfo> ImplicitNodes;
-  auto CurSyntax = PendingSyntax.begin();
-  for (auto It = Tokens.begin(); It->getStartLoc() != EndLoc;) {
-    auto Tok = *It;
-    if (CurSyntax == PendingSyntax.end()) {
-      // If no remaining syntax nodes, add the token.
-      addNodeToResults(Results, ImplicitNodes, Tok);
-      It ++;
-    } else if (CurSyntax->isImplicit()) {
-      ImplicitNodes.emplace_back(*CurSyntax);
-      // Skip implicit syntax node.
-      CurSyntax ++;
-    } else if (CurSyntax->getStartLoc() == Tok.getStartLoc()) {
-      // Prefer syntax nodes to tokens.
-      addNodeToResults(Results, ImplicitNodes, *CurSyntax);
-      while(It->getEndLoc() != CurSyntax->getEndLoc()) It++;
-      assert(It < Tokens.end() && It->getEndLoc() == CurSyntax->getEndLoc());
-      It ++;
-      CurSyntax ++;
-    } else {
-      // We have to add token in this case since the next syntax node has not
-      // started.
-      assert(Tok.getStartLoc().getOpaquePointerValue() <
-             CurSyntax->getStartLoc().getOpaquePointerValue());
-      addNodeToResults(Results, ImplicitNodes, Tok);
-      It ++;
-    }
-  }
-  // Add the remaining syntax nodes.
-  for (;CurSyntax != PendingSyntax.end(); CurSyntax ++) {
-    Results.emplace_back(*CurSyntax);
-  }
-  return Results;
+/// Add RawSyntax to the parts.
+void SyntaxParsingContext::addRawSyntax(RC<RawSyntax> Raw) {
+  Parts.emplace_back(Raw);
 }
 
-void SyntaxParsingContext::ContextInfo::
-createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse,
-                        unsigned N) {
-  auto Size = NodesToUse.size();
-  assert(N && Size >= N);
-  auto Parts = llvm::makeArrayRef(NodesToUse).slice(Size - N);
-
-  // Count the parts from the pending syntax list.
-  unsigned UsedPending = std::accumulate(Parts.begin(), Parts.end(), 0,
-    [](unsigned Count, RawSyntaxInfo Info) {
-      return Count += Info.RawNode->isToken() ? 0 : 1;
-    });
-
-  // Remove all pending syntax ndoes that we used to create the new node.
-  for (unsigned I = 0; I < UsedPending; I ++)
-    PendingSyntax.pop_back();
-
-  // Add result to the pending syntax list.
-  addPendingSyntax(createSyntaxAs(Parts, Kind));
+SyntaxParsingContext *SyntaxParsingContext::getRoot() {
+  auto Curr = this;
+  while (!Curr->isRoot())
+    Curr = Curr->Parent;
+  return Curr;
 }
 
-void SyntaxParsingContext::ContextInfo::
-createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse) {
-  auto Result = createSyntaxAs(NodesToUse, Kind);
-  PendingSyntax.clear();
-  addPendingSyntax(Result);
-}
-
-SyntaxParsingContext::
-SyntaxParsingContext(SourceFile &SF, unsigned BufferID, Token &Tok):
-  ContextData(*new ContextInfo(SF, BufferID)),
-    Tok(Tok) {}
-
-SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext &Another):
-  ContextData(*new ContextInfo(Another.ContextData.allTokens(),
-    Another.ContextData.Enabled)), Tok(Another.Tok) {}
-
-SyntaxParsingContext::~SyntaxParsingContext() { delete &ContextData; }
-
-void SyntaxParsingContext::disable() { ContextData.Enabled = false; }
-
-SyntaxParsingContextRoot::~SyntaxParsingContextRoot() {
-  if (!ContextData.Enabled)
+/// Add Token with Trivia to the parts.
+void SyntaxParsingContext::addToken(Token &Tok, Trivia &LeadingTrivia,
+                                    Trivia &TrailingTrivia) {
+  if (!Enabled)
     return;
-  std::vector<DeclSyntax> AllTopLevel;
-  if (File.hasSyntaxRoot()) {
-    for (auto It: File.getSyntaxRoot().getTopLevelDecls()) {
-      AllTopLevel.push_back(It);
-    }
+
+  if (Tok.isEscapedIdentifier()) {
+    LeadingTrivia.push_back(TriviaPiece::backtick());
+    TrailingTrivia.push_front(TriviaPiece::backtick());
   }
-  for (auto Info: ContextData.getPendingSyntax()) {
-    assert(Info.RawNode->Kind == SyntaxKind::StmtList);
-    AllTopLevel.push_back(SyntaxFactory::makeTopLevelCodeDecl(
-      Info.makeSyntax<StmtListSyntax>()));
-  }
-
-  File.setSyntaxRoot(
-    SyntaxFactory::makeSourceFile(SyntaxFactory::makeDeclList(AllTopLevel),
-    // The last node must be eof.
-    ContextData.allTokens().back().makeSyntax<TokenSyntax>()));
+  addRawSyntax(RawTokenSyntax::make(Tok.getKind(), Tok.getText(),
+                                    SourcePresence::Present, LeadingTrivia,
+                                    TrailingTrivia));
 }
 
-SyntaxParsingContextRoot &SyntaxParsingContextChild::getRoot() {
-  for (SyntaxParsingContext *Root = getParent(); ;
-       Root = static_cast<SyntaxParsingContextChild*>(Root)->getParent()){
-    if (Root->getKind() == SyntaxParsingContextKind::Root)
-      return *static_cast<SyntaxParsingContextRoot*>(Root);
-  }
-  llvm_unreachable("can not find root");
+/// Add Syntax to the parts.
+void SyntaxParsingContext::addSyntax(Syntax Node) {
+  if (!Enabled)
+    return;
+  addRawSyntax(Node.getRaw());
 }
 
-SyntaxParsingContextChild::
-SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-      Optional<SyntaxContextKind> ContextKind, Optional<SyntaxKind> KnownSyntax):
-    SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
-    ContextHolder(ContextHolder), ContextKind(ContextKind),
-    KnownSyntax(KnownSyntax) {
-  ContextHolder = this;
-  if (ContextData.Enabled)
-    ContextData.setContextStart(Tok.getLoc());
+void SyntaxParsingContext::createNodeInPlace(SyntaxKind Kind, size_t N) {
+  assert(N >= 1);
+
+  auto I = Parts.end() - N;
+  *I = createSyntaxAs(Kind, llvm::makeArrayRef(Parts).take_back(N));
+
+  // Remove used parts.
+  if (N != 1)
+    Parts.erase(I + 1, Parts.end());
 }
 
-void SyntaxParsingContextChild::setSyntaxKind(SyntaxKind SKind) {
-  assert(!KnownSyntax.hasValue() && "reset");
-  KnownSyntax = SKind;
-  ContextKind = None;
-}
-
-void SyntaxParsingContextChild::setContextKind(SyntaxContextKind CKind) {
-  assert(!ContextKind.hasValue() && "reset");
-  ContextKind = CKind;
-  KnownSyntax = None;
-}
-
-SyntaxParsingContextChild::
-SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder, bool Disable):
-    SyntaxParsingContextChild(ContextHolder, None, None) {
-  if (Disable)
-    disable();
-}
-
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc EndLoc) {
+void SyntaxParsingContext::createNodeInPlace(SyntaxKind Kind) {
   assert(isTopOfContextStack());
-  if (!ContextData.Enabled)
+  if (!Enabled)
     return;
 
-  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
-
-  // Create syntax nodes according to the given kind.
   switch (Kind) {
-  case SyntaxKind::FloatLiteralExpr:
-  case SyntaxKind::IntegerLiteralExpr: {
-    // Integer may include the signs before the digits, so check if the sign
-    // exists and create.
-    ContextData.createPartiallyFromBack(Kind, AllNodes, ContextData.
-      checkTokenFromBack(tok::oper_prefix, AllNodes, 1) ? 2 : 1);
-    break;
-  }
-  case SyntaxKind::TernaryExpr:
-  case SyntaxKind::StringLiteralExpr: {
+  case SyntaxKind::MemberAccessExpr:
+  case SyntaxKind::TernaryExpr: {
     auto Pair = SyntaxFactory::countChildren(Kind);
     assert(Pair.first == Pair.second);
-    ContextData.createPartiallyFromBack(Kind, AllNodes, Pair.first);
+    createNodeInPlace(Kind, Pair.first);
+    break;
+  }
+  case SyntaxKind::ExprList: {
+    createNodeInPlace(Kind, Parts.size());
     break;
   }
   default:
@@ -342,144 +126,140 @@
   }
 }
 
-void SyntaxParsingContextChild::makeNodeWhole(SyntaxKind Kind) {
-  assert(ContextData.Enabled);
-  assert(isTopOfContextStack());
-
-  auto EndLoc = Tok.getLoc();
-  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
-  switch (Kind) {
-  case SyntaxKind::BooleanLiteralExpr:
-  case SyntaxKind::NilLiteralExpr:
-  case SyntaxKind::DiscardAssignmentExpr:
-  case SyntaxKind::IdentifierExpr:
-  case SyntaxKind::DictionaryExpr:
-  case SyntaxKind::ArrayExpr:
-  case SyntaxKind::DictionaryElement:
-  case SyntaxKind::ArrayElement:
-  case SyntaxKind::FunctionCallArgument:
-  case SyntaxKind::ReturnStmt:
-  case SyntaxKind::CodeBlock: {
-    ContextData.createWhole(Kind, AllNodes);
-    break;
-  }
-  case SyntaxKind::DictionaryElementList:
-  case SyntaxKind::ArrayElementList:
-  case SyntaxKind::StmtList:
-  case SyntaxKind::FunctionCallArgumentList: {
-    if (AllNodes.empty()) {
-      // Create an empty argument list if no arguments are in the context.
-      RawSyntaxInfo Empty(SyntaxFactory::
-                          makeBlankCollectionSyntax(Kind).getRaw());
-      Empty.setBeforeLoc(EndLoc);
-      ContextData.addPendingSyntax(Empty);
-    } else {
-      ContextData.createWhole(Kind, AllNodes);
+namespace {
+RC<RawSyntax> bridgeAs(SyntaxContextKind Kind, ArrayRef<RC<RawSyntax>> Parts) {
+  if (Parts.size() == 1) {
+    auto RawNode = Parts.front();
+    switch (Kind) {
+    case SyntaxContextKind::Stmt: {
+      if (RawNode->isStmt())
+        return RawNode;
+      else if (RawNode->isDecl())
+        return createSyntaxAs(SyntaxKind::DeclarationStmt, Parts);
+      else if (RawNode->isExpr())
+        return createSyntaxAs(SyntaxKind::ExpressionStmt, Parts);
+      else
+        return makeUnknownSyntax(SyntaxKind::UnknownStmt, Parts);
+      break;
     }
-    break;
-  }
-  default:
-    llvm_unreachable("Unrecognized node kind.");
-  }
-}
-
-void RawSyntaxInfo::brigeWithContext(SyntaxContextKind Kind) {
-  switch (Kind) {
-  case SyntaxContextKind::Stmt: {
-    if (RawNode->isDecl()) {
-      // Wrap a declaration with a declaration statement
-      RawNode = SyntaxFactory::createSyntax(SyntaxKind::DeclarationStmt,
-        { makeSyntax<Syntax>() })->getRaw();
-    } else if (RawNode->isExpr()) {
-      // Wrap an expression with an expression statement
-      RawNode = SyntaxFactory::createSyntax(SyntaxKind::ExpressionStmt,
-        { makeSyntax<Syntax>() })->getRaw();
-    } else if (RawNode->isToken()) {
-      // Wrap a standalone token withn an expression statement
-      RawNode = SyntaxFactory::createSyntax(SyntaxKind::ExpressionStmt,
-        makeUnknownSyntax(SyntaxKind::UnknownExpr,
-                          {make<Syntax>(RawNode)}))->getRaw();
-    }
-    assert(RawNode->isStmt());
-    break;
-  }
-  case SyntaxContextKind::Decl: {
-    if (!RawNode->isDecl()) {
-      RawNode = makeUnknownSyntax(SyntaxKind::UnknownDecl,
-                                  {make<Syntax>(RawNode)}).getRaw();
-    }
-    assert(RawNode->isDecl());
-    break;
-  }
-
-  case SyntaxContextKind::Expr:
-    if (!RawNode->isExpr()) {
-      RawNode = makeUnknownSyntax(SyntaxKind::UnknownExpr,
-                                  {make<Syntax>(RawNode)}).getRaw();
-    }
-    assert(RawNode->isExpr());
-    break;
-  }
-}
-
-void SyntaxParsingContextChild::finalize() {
-  assert(isTopOfContextStack());
-  SWIFT_DEFER {
-    // Reset the context holder to be Parent.
-    ContextHolder = Parent;
-  };
-  if (!ContextData.Enabled)
-    return;
-
-  assert(ContextKind.hasValue() != KnownSyntax.hasValue());
-  SourceLoc EndLoc = Tok.getLoc();
-  if (KnownSyntax) {
-    // If the entire context should be created to a known syntax kind, create
-    // all pending syntax nodes into that node.
-    makeNodeWhole(*KnownSyntax);
-    assert(ContextData.getPendingSyntax().size() == 1);
-    Parent->ContextData.addPendingSyntax(ContextData.getPendingSyntax().front());
-    return;
-  }
-  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
-  RC<RawSyntax> FinalResult;
-  if (AllNodes.empty())
-    return;
-
-  // Make sure we used all tokens.
-  assert(AllNodes.front().getStartLoc() == ContextData.getContextStartLoc());
-
-  if (AllNodes.size() == 1) {
-    // If we have only one syntax node remaining, we are done.
-    auto Result = AllNodes.front();
-    // Bridge the syntax node to the expected context kind.
-    Result.brigeWithContext(*ContextKind);
-    Parent->ContextData.addPendingSyntax(Result);
-    return;
-  }
-
-  llvm::SmallVector<Syntax, 8> Scratch;
-  auto SyntaxNodes = getSyntaxNodes(AllNodes, Scratch);
-  SourceLoc Start = AllNodes.front().getStartLoc();
-  SourceLoc End = AllNodes.back().getEndLoc();
-  SyntaxKind UnknownKind;
-  switch (*ContextKind) {
+    case SyntaxContextKind::Decl:
+      if (!RawNode->isDecl())
+        return makeUnknownSyntax(SyntaxKind::UnknownDecl, Parts);
+      break;
     case SyntaxContextKind::Expr:
-      UnknownKind = SyntaxKind::UnknownExpr;
+      if (!RawNode->isExpr())
+        return makeUnknownSyntax(SyntaxKind::UnknownExpr, Parts);
+      break;
+    case SyntaxContextKind::Type:
+      if (!RawNode->isType())
+        return makeUnknownSyntax(SyntaxKind::UnknownType, Parts);
+      break;
+    case SyntaxContextKind::Pattern:
+      if (!RawNode->isPattern())
+        return makeUnknownSyntax(SyntaxKind::UnknownPattern, Parts);
+      break;
+    }
+    return RawNode;
+  } else {
+    SyntaxKind UnknownKind;
+    switch (Kind) {
+    case SyntaxContextKind::Stmt:
+      UnknownKind = SyntaxKind::UnknownStmt;
       break;
     case SyntaxContextKind::Decl:
       UnknownKind = SyntaxKind::UnknownDecl;
       break;
-    case SyntaxContextKind::Stmt:
-      UnknownKind = SyntaxKind::UnknownStmt;
+    case SyntaxContextKind::Expr:
+      UnknownKind = SyntaxKind::UnknownExpr;
       break;
+    case SyntaxContextKind::Type:
+      UnknownKind = SyntaxKind::UnknownType;
+      break;
+    case SyntaxContextKind::Pattern:
+      UnknownKind = SyntaxKind::UnknownPattern;
+      break;
+    }
+    return makeUnknownSyntax(UnknownKind, Parts);
   }
-  // Create an unknown node and give it to the parent context.
-  Parent->ContextData.addPendingSyntax({SourceRange(Start, End),
-    makeUnknownSyntax(UnknownKind, SyntaxNodes).getRaw()});
 }
 
-SyntaxParsingContextChild::~SyntaxParsingContextChild() {
-  if (isTopOfContextStack())
-    finalize();
+void finalizeSourceFile(SourceFile *SF, ArrayRef<RC<RawSyntax>> Parts) {
+  std::vector<DeclSyntax> AllTopLevel;
+  llvm::Optional<TokenSyntax> EOFToken;
+
+  if (SF->hasSyntaxRoot()) {
+    EOFToken.emplace(SF->getSyntaxRoot().getEOFToken());
+    for (auto It : SF->getSyntaxRoot().getTopLevelDecls()) {
+      AllTopLevel.push_back(It);
+    }
+  }
+
+  if (Parts.back()->isToken() &&
+      cast<RawTokenSyntax>(Parts.back())->is(tok::eof)) {
+    EOFToken.emplace(make<TokenSyntax>(Parts.back()));
+    Parts = Parts.drop_back();
+  }
+
+  for (auto RawNode : Parts) {
+    if (RawNode->Kind != SyntaxKind::StmtList)
+      // FIXME: Skip for now.
+      continue;
+    AllTopLevel.push_back(
+        SyntaxFactory::makeTopLevelCodeDecl(make<StmtListSyntax>(RawNode)));
+  }
+  SF->setSyntaxRoot(SyntaxFactory::makeSourceFile(
+      SyntaxFactory::makeDeclList(AllTopLevel),
+      EOFToken.hasValue() ? *EOFToken
+                          : TokenSyntax::missingToken(tok::eof, "")));
+}
+
+} // End of anonymous namespace
+
+SyntaxParsingContext::~SyntaxParsingContext() {
+  assert(isTopOfContextStack() && "destructed in wrong order");
+
+  SWIFT_DEFER {
+    // Pop this context from the stack.
+    if (!isRoot())
+      CtxtHolder = Parent;
+  };
+
+  if (!Enabled)
+    return;
+
+  switch (Mode) {
+  // Create specified Syntax node from the parts and add it to the parent.
+  case AccumulationMode::CreateSyntax:
+    assert(!isRoot());
+    Parent->addRawSyntax(createSyntaxAs(SynKind, Parts));
+    break;
+
+  // Ensure the result is specified Syntax category and add it to the parent.
+  case AccumulationMode::CoerceKind:
+    assert(!isRoot());
+    Parent->addRawSyntax(bridgeAs(CtxtKind, Parts));
+    break;
+
+  // Just move the parts to the tail of the parent.
+  case AccumulationMode::Transparent:
+    assert(!isRoot());
+    std::move(Parts.begin(), Parts.end(), std::back_inserter(Parent->Parts));
+    break;
+
+  // Do nothing. Just let it discarded.
+  case AccumulationMode::Discard:
+    assert(!isRoot());
+    break;
+
+  // Accumulate parsed toplevel syntax onto the SourceFile.
+  case AccumulationMode::Root:
+    assert(isRoot() && "AccumulationMode::Root is only for root context");
+    finalizeSourceFile(SF, Parts);
+    break;
+
+  // Never.
+  case AccumulationMode::NotSet:
+    assert(!Enabled && "Cleanup mode must be spefcified before destruction");
+    break;
+  }
 }
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/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..898e0a8 100644
--- a/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
+++ b/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
@@ -94,14 +94,14 @@
     _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)
   }
 }
 
@@ -113,10 +113,10 @@
     _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)
   }
 }
 
@@ -130,11 +130,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)}
@@ -167,15 +167,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.
@@ -237,17 +237,17 @@
               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)
   }
 }
 
@@ -262,17 +262,17 @@
               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)
   }
 }
 
@@ -281,10 +281,10 @@
   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..a0924ad 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))
   }
 }
 
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/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index 7523a29..6919b52 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
@@ -1377,7 +1377,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)
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/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/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..be63327 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: NSMakeRange(range.lowerBound, range.count), value: value)
     }
 }
 
@@ -28,13 +28,13 @@
 #if os(OSX)
     @available(macOS, introduced: 10.11)
     public func didModifyRange(_ range: Range<Int>) {
-        didModifyRange(NSMakeRange(range.lowerBound, range.count))
+        __didModifyRange(NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, range.count))
     }
 }
 
@@ -76,7 +76,7 @@
     @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
     }
 }
@@ -87,7 +87,7 @@
 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: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
     }
 }
 
@@ -125,56 +125,56 @@
     
     @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)
     @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: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setVertexTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setVertexTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setVertexSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setVertexSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexSamplerStates(samplers, with: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setFragmentTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setFragmentTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
     }
     
     public func setFragmentSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setFragmentSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentSamplerStates(samplers, with: NSMakeRange(range.lowerBound, 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: NSMakeRange(range.lowerBound, range.count))
     }
 
 #if os(iOS)
@@ -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: NSMakeRange(levelRange.lowerBound, levelRange.count), slices: NSMakeRange(sliceRange.lowerBound, 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/SceneKit/SceneKit.swift.gyb b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
index e4eb4ca..21e8405 100644
--- a/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
+++ b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
@@ -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/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/os/os_trace_blob.c b/stdlib/public/SDK/os/os_trace_blob.c
index 86c070b..81c86f1 100644
--- a/stdlib/public/SDK/os/os_trace_blob.c
+++ b/stdlib/public/SDK/os/os_trace_blob.c
@@ -14,7 +14,10 @@
 #include <dispatch/dispatch.h>
 #include <os/base.h>
 #include <os/log.h>
+#include <locale.h>
+#if !defined(__linux__)
 #include <xlocale.h>
+#endif
 #include "os_trace_blob.h"
 
 OS_NOINLINE
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/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/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..9558316 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.
   ///
@@ -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..9e17e41 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -47,7 +47,8 @@
   CString.swift
   CTypes.swift
   DebuggerSupport.swift
-  DoubleWidth.swift.gyb
+  # FIXME(double-width): <rdar://problem/32726173>
+  #DoubleWidth.swift.gyb
   DropWhile.swift.gyb
   Dump.swift
   EmptyCollection.swift
@@ -72,7 +73,7 @@
   HeapBuffer.swift
   ICU.swift
   ImplicitlyUnwrappedOptional.swift
-  Indices.swift.gyb
+  Indices.swift
   InputStream.swift
   IntegerParsing.swift
   Integers.swift.gyb
@@ -100,7 +101,7 @@
   Print.swift
   RandomAccessCollection.swift
   Range.swift.gyb
-  RangeReplaceableCollection.swift.gyb
+  RangeReplaceableCollection.swift
   ReflectionLegacy.swift
   Repeat.swift
   REPL.swift
@@ -115,7 +116,7 @@
   SetAlgebra.swift
   ShadowProtocols.swift
   Shims.swift
-  Slice.swift.gyb
+  Slice.swift
   Sort.swift.gyb
   StaticString.swift
   Stride.swift.gyb
@@ -227,6 +228,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 +252,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 fd6a624..b3211dd 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,38 +82,15 @@
   }
 }
 
-// FIXME(ABI)#175 (Type checker)
-// WORKAROUND: needed because of rdar://25584401
-/// An iterator over the elements of a `CountableClosedRange` instance.
-@_fixed_layout
-public struct ClosedRangeIterator<Bound> : IteratorProtocol, Sequence
-  where
-  Bound : Strideable, Bound.Stride : SignedInteger {
-
-  @_inlineable
-  @_versioned
-  internal init(_range r: CountableClosedRange<Bound>) {
-    _nextResult = r.lowerBound
-    _upperBound = r.upperBound
-  }
-
-  @_inlineable
-  public func makeIterator() -> ClosedRangeIterator {
-    return self
-  }
-
-  @_inlineable
-  public mutating func next() -> Bound? {
-    let r = _nextResult
-    if let x = r {
-      _nextResult = x == _upperBound ? nil : x.advanced(by: 1)
+extension ClosedRangeIndex : Hashable where Bound : Hashable {
+  public var hashValue: Int {
+    switch _value {
+    case .inRange(let value):
+      return value.hashValue
+    case .pastEnd:
+      return .max
     }
-    return r
   }
-  @_versioned
-  internal var _nextResult: Bound?
-  @_versioned
-  internal let _upperBound: Bound
 }
 
 /// A closed range that forms a collection of consecutive values.
@@ -166,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
@@ -179,25 +152,29 @@
   /// 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
 
-  // FIXME(ABI)#175 (Type checker)
-  // WORKAROUND: needed because of rdar://25584401
-  public typealias Iterator = ClosedRangeIterator<Bound>
-
-  // FIXME(ABI)#175 (Type checker)
-  // WORKAROUND: needed because of rdar://25584401
-  @_inlineable
-  public func makeIterator() -> ClosedRangeIterator<Bound> {
-    return ClosedRangeIterator(_range: self)
-  }
-
   /// The position of the first element in the range.
   @_inlineable
   public var startIndex: ClosedRangeIndex<Bound> {
@@ -295,32 +272,8 @@
 
   @_inlineable
   public subscript(bounds: Range<Index>)
-    -> RandomAccessSlice<CountableClosedRange<Bound>> {
-    return RandomAccessSlice(base: self, bounds: bounds)
-  }
-
-  // FIXME(ABI)#175 (Type checker)
-  @_inlineable
-  public // WORKAROUND: needed because of rdar://25584401
-  var indices: DefaultRandomAccessIndices<CountableClosedRange<Bound>> {
-    return DefaultRandomAccessIndices(
-      _elements: self,
-      startIndex: self.startIndex,
-      endIndex: self.endIndex)
-  }
-
-  /// 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
@@ -375,9 +328,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.
   ///
@@ -393,12 +350,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.
   ///
@@ -440,8 +391,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..b4226c6 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
 
@@ -403,7 +405,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>
+  associatedtype SubSequence = Slice<Self>
     where SubSequence.Index == Index,
           SubSequence.IndexDistance == IndexDistance
 
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..a8b43de 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,24 @@
 
 /// 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 {
@@ -155,8 +162,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..e585ba5 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
@@ -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,25 @@
 /// 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 IndexDistance = Int64
+  public typealias SubSequence = ${Self}<Element> 
 
 %   for SubTraversal in TRAVERSALS[ti:]:
 %     SubProtocol = collectionForTraversal(SubTraversal)
@@ -1046,10 +1056,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 +1067,7 @@
   ///
   /// - Complexity: O(1)
   @_inlineable
-  public init(
-    _ other: Any${SubProtocol}<Element>
-  ) {
+  public init(_ other: Any${SubProtocol}<Element>) {
     self._box = other._box
   }
 %   end
@@ -1075,9 +1080,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 +1089,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 +1103,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 +1112,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 +1137,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 +1152,20 @@
   }
 
   @_inlineable
-  public func index(_ i: AnyIndex, offsetBy n: Int64) -> AnyIndex {
+  public func index(_ i: Index, offsetBy n: Int64) -> 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: IndexDistance, 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: IndexDistance) {
     if _isUnique(&i._box) {
       return _box._formIndex(&i._box, offsetBy: n)
     } else {
@@ -1177,9 +1175,9 @@
 
   @_inlineable
   public func formIndex(
-    _ i: inout AnyIndex,
-    offsetBy n: Int64,
-    limitedBy limit: AnyIndex
+    _ i: inout Index,
+    offsetBy n: IndexDistance,
+    limitedBy limit: Index
   ) -> Bool {
     if _isUnique(&i._box) {
       return _box._formIndex(&i._box, offsetBy: n, limitedBy: limit._box)
@@ -1193,7 +1191,7 @@
   }
 
   @_inlineable
-  public func distance(from start: AnyIndex, to end: AnyIndex) -> Int64 {
+  public func distance(from start: Index, to end: Index) -> IndexDistance {
     return _box._distance(from: start._box, to: end._box)
   }
 
@@ -1207,7 +1205,7 @@
 % end
   /// - Complexity: ${'O(1)' if Traversal == 'RandomAccess' else 'O(*n*)'}
   @_inlineable
-  public var count: Int64 {
+  public var count: IndexDistance {
     return _box._count
   }
 
@@ -1218,12 +1216,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 +1235,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/Flatten.swift.gyb b/stdlib/public/core/Flatten.swift.gyb
index f68e7b9..4510064 100644
--- a/stdlib/public/core/Flatten.swift.gyb
+++ b/stdlib/public/core/Flatten.swift.gyb
@@ -220,6 +220,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
@@ -354,8 +362,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 7ac7007..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)
@@ -2054,27 +2161,6 @@
     }
   }
 
-  /// 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.
   ///
@@ -2352,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.
@@ -2711,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) {
@@ -5992,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
@@ -6114,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..0e1f601 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,16 @@
     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 IndexDistance = Elements.IndexDistance
+	public typealias Iterator = IndexingIterator<DefaultIndices<Elements>>
 
   @_inlineable
   public var startIndex: Index {
@@ -65,12 +58,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 +79,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 +98,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 +122,13 @@
   ///     }
   ///     // 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:
+public typealias DefaultBidirectionalIndices<T: BidirectionalCollection> = DefaultIndices<T>
+public typealias DefaultRandomAccessIndices<T: RandomAccessCollection> = DefaultIndices<T>
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 9d7fc5f..dba809e 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -2907,7 +2907,7 @@
   /// Creates a new instance with the same memory representation as the given
   /// value.
   ///
-  /// This initializer does not perform any range or overflow checking. The the
+  /// This initializer does not perform any range or overflow checking. The
   /// resulting instance may not have the same numeric value as
   /// `bitPattern`---it is only guaranteed to use the same pattern of bits in
   /// its binary representation.
@@ -3208,7 +3208,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}
@@ -3378,14 +3378,15 @@
   ) -> (quotient: ${Self}, remainder: ${Self}) {
     // FIXME(integers): tests
 %   # 128 bit types are not provided by the 32-bit LLVM
-%   #if word_bits == 32 and bits == 64:
-%   if bits == 64:
-    let lhs = DoubleWidth<${Self}>(dividend)
-    let rhs = DoubleWidth<${Self}>(self)
+%   if word_bits == 32 and bits == 64:
+%   #if bits == 64: #FIXME(double-width): uncomment when DoubleWidth is back
+    // let lhs = DoubleWidth<${Self}>(dividend)
+    // let rhs = DoubleWidth<${Self}>(self)
 
-    let (quotient, remainder) = lhs.quotientAndRemainder(dividingBy: rhs)
+    // let (quotient, remainder) = lhs.quotientAndRemainder(dividingBy: rhs)
     // FIXME(integers): check for high words in quotient and remainder
-    return (${Self}(quotient.low), ${Self}(remainder.low))
+    // return (${Self}(quotient.low), ${Self}(remainder.low))
+    fatalError("Operation is not supported")
 %   else:
     // FIXME(integers): handle division by zero and overflows
     _precondition(self != 0, "Division by zero")
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 6582ca7..49c7774 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -1713,7 +1713,7 @@
   /// `arrayDescription`, `String`.
   ///
   /// - Parameter path: The key path to append.
-  /// - Returns: A key path from the root of this key path to the the value type
+  /// - Returns: A key path from the root of this key path to the value type
   ///   of `path`, if `path` can be appended. If `path` can't be appended,
   ///   returns `nil`.
   @_inlineable // FIXME(sil-serialize-all)
@@ -1732,7 +1732,7 @@
   /// root type for `path` matches this key path's value type.
   ///
   /// - Parameter path: The reference writeable key path to append.
-  /// - Returns: A key path from the root of this key path to the the value type
+  /// - Returns: A key path from the root of this key path to the value type
   ///   of `path`, if `path` can be appended. If `path` can't be appended,
   ///   returns `nil`.
   @_inlineable // FIXME(sil-serialize-all)
@@ -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..8244cd7 100644
--- a/stdlib/public/core/LazyCollection.swift.gyb
+++ b/stdlib/public/core/LazyCollection.swift.gyb
@@ -162,8 +162,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<${Self}<Base>> {
+    return Slice(base: self, bounds: bounds)
   }
 
   /// A Boolean value indicating whether the collection is empty.
@@ -266,6 +266,9 @@
 
 % end
 
+extension Slice: LazySequenceProtocol where Base: LazySequenceProtocol { }
+extension Slice: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
+
 // ${'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/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..3a47000 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:).
 
diff --git a/stdlib/public/core/Range.swift.gyb b/stdlib/public/core/Range.swift.gyb
index 7f1e249..b717db6 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,31 @@
   /// 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 {
@@ -211,14 +220,12 @@
     return 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 +238,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 +245,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 +313,7 @@
 }
 
 extension CountableRange
-  where
+where
   Bound._DisabledRangeIndex : Strideable,
   Bound._DisabledRangeIndex.Stride : SignedInteger {
 
@@ -401,9 +392,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 +418,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 +756,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 +800,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 +843,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 +946,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 +971,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 +980,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..b21505c 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
 //
@@ -70,10 +70,11 @@
 /// `replaceSubrange(_:with:)` with an empty collection for the `newElements` 
 /// parameter. You can override any of the protocol's required methods to 
 /// provide your own custom implementation.
-public protocol RangeReplaceableCollection : Collection
+public protocol RangeReplaceableCollection: Collection
+where SubSequence: RangeReplaceableCollection
 {
-  associatedtype SubSequence : RangeReplaceableCollection
-    = RangeReplaceableSlice<Self>
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype SubSequence = Slice<Self>
 
   //===--- Fundamental Requirements ---------------------------------------===//
 
@@ -365,11 +366,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.
   ///
@@ -655,40 +651,6 @@
   public mutating func reserveCapacity(_ n: IndexDistance) {}
 }
 
-// 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.
   ///
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..cb35cc3 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,13 +176,14 @@
   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
@@ -248,7 +247,8 @@
     _ i: Index, offsetBy n: IndexDistance, 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
@@ -262,184 +262,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 +304,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,
@@ -533,12 +330,8 @@
   /// - Complexity: O(1)
   @_inlineable
   public func reversed() -> LazyRandomAccessCollection<
-    ReversedRandomAccessCollection<Elements>
+    ReversedCollection<Elements>
   > {
-    return ReversedRandomAccessCollection(_base: elements).lazy
+    return ReversedCollection(_base: elements).lazy
   }
 }
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
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 76%
rename from stdlib/public/core/Slice.swift.gyb
rename to stdlib/public/core/Slice.swift
index 77bc621..a5400c4 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,43 +71,79 @@
 ///   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
 
+  @_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.
+  ///
+  /// It is unusual to need to call this method directly. Instead, create a
+  /// slice of a collection by using the collection's range-based subscript or
+  /// by using methods that return a subsequence.
+  ///
+  ///     let singleDigits = 0...9
+  ///     let subSequence = singleDigits.dropFirst(5)
+  ///     print(Array(subSequence))
+  ///     // Prints "[5, 6, 7, 8, 9]"
+  ///
+  /// In this example, the expression `singleDigits.dropFirst(5))` is
+  /// equivalent to calling this initializer with `singleDigits` and a
+  /// range covering the last five items of `singleDigits.indices`.
+  ///
+  /// - Parameters:
+  ///   - 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<Base.Index>) {
+    self._base = base
+    self._startIndex = bounds.lowerBound
+    self._endIndex = bounds.upperBound
+  }
+
+  /// The underlying collection of the slice.
+  ///
+  /// You can use a slice's `base` property to access its base collection. The
+  /// following example declares `singleDigits`, a range of single digit
+  /// integers, and then drops the first element to create a slice of that
+  /// range, `singleNonZeroDigits`. The `base` property of the slice is equal
+  /// to `singleDigits`.
+  ///
+  ///     let singleDigits = 0..<10
+  ///     let singleNonZeroDigits = singleDigits.dropFirst()
+  ///     // singleNonZeroDigits is a Slice<CountableRange<Int>>
+  ///
+  ///     print(singleNonZeroDigits.count)
+  ///     // Prints "9"
+  ///     prints(singleNonZeroDigits.base.count)
+  ///     // Prints "10"
+  ///     print(singleDigits == singleNonZeroDigits.base)
+  ///     // Prints "true"
+  @_inlineable // FIXME(sil-serialize-all)
+  public var base: Base {
+    return _base
+  }
+}
+
+extension Slice: Collection {
   public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
   public typealias IndexDistance = Base.IndexDistance  
-
-  public var _startIndex: Index
-  public var _endIndex: Index
+  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 {
@@ -137,33 +161,16 @@
       _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> {
+  public subscript(bounds: Range<Index>) -> Slice<Base> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return ${Self}(base: _base, bounds: bounds)
+      return Slice(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]
   }
@@ -180,20 +187,6 @@
     _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.
@@ -223,8 +216,55 @@
   public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
     _base._failEarlyRangeCheck(range, bounds: bounds)
   }
+}
 
-%     if RangeReplaceable:
+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()
@@ -240,11 +280,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public init<S>(_ elements: S)
-    where
-    S : Sequence,
-    S.Element == Base.Element {
-
+  public init<S>(_ elements: S) where S: Sequence, S.Element == Base.Element {
     self._base = Base(elements)
     self._startIndex = _base.startIndex
     self._endIndex = _base.endIndex
@@ -253,12 +289,9 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func replaceSubrange<C>(
     _ subRange: Range<Index>, with newElements: C
-  ) where
-    C : Collection,
-    C.Element == Base.Element {
+  ) 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 =
@@ -268,7 +301,66 @@
     _base.replaceSubrange(subRange, with: newElements)
     _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
     _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-%     else:
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func insert(_ newElement: Base.Element, at i: Index) {
+    // FIXME: swift-3-indexing-model: range check.
+    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)
+  }
+
+  @_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: 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)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func remove(at i: Index) -> Base.Element {
+    // FIXME: swift-3-indexing-model: range check.
+    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
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    // FIXME: swift-3-indexing-model: range check.
+    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)
+  }
+}
+
+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: IndexDistance =
         _base.distance(from: _startIndex, to: subRange.lowerBound)
@@ -289,20 +381,11 @@
       }
       _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)
@@ -318,25 +401,12 @@
       }
       _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 {
-
+  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)
@@ -355,21 +425,11 @@
       }
       _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)
@@ -387,21 +447,11 @@
       _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
@@ -422,68 +472,31 @@
       }
       _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
     }
-%     end
-  }
-%     end
-
-  /// Creates a view into the given collection that allows access to elements
-  /// within the specified range.
-  ///
-  /// It is unusual to need to call this method directly. Instead, create a
-  /// slice of a collection by using the collection's range-based subscript or
-  /// by using methods that return a subsequence.
-  ///
-  ///     let singleDigits = 0...9
-  ///     let subSequence = singleDigits.dropFirst(5)
-  ///     print(Array(subSequence))
-  ///     // Prints "[5, 6, 7, 8, 9]"
-  ///
-  /// In this example, the expression `singleDigits.dropFirst(5))` is
-  /// equivalent to calling this initializer with `singleDigits` and a
-  /// range covering the last five items of `singleDigits.indices`.
-  ///
-  /// - Parameters:
-  ///   - 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>) {
-    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
-  /// following example declares `singleDigits`, a range of single digit
-  /// integers, and then drops the first element to create a slice of that
-  /// range, `singleNonZeroDigits`. The `base` property of the slice is equal
-  /// to `singleDigits`.
-  ///
-  ///     let singleDigits = 0..<10
-  ///     let singleNonZeroDigits = singleDigits.dropFirst()
-  ///     // singleNonZeroDigits is a RandomAccessSlice<CountableRange<Int>>
-  ///
-  ///     print(singleNonZeroDigits.count)
-  ///     // Prints "9"
-  ///     prints(singleNonZeroDigits.base.count)
-  ///     // Prints "10"
-  ///     print(singleDigits == singleNonZeroDigits.base)
-  ///     // Prints "true"
-  @_inlineable // FIXME(sil-serialize-all)
-  public var base: Base {
-    return _base
   }
 }
 
-%     end
-%   end
-% end
+@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, T: BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T: RangeReplaceableCollection, T: RandomAccessCollection
+
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableSlice<T: MutableCollection> = Slice<T>
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableBidirectionalSlice<T: MutableCollection> = Slice<T> where T: BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRandomAccessSlice<T: MutableCollection> = Slice<T> where T: RandomAccessCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableSlice<T: MutableCollection> = Slice<T> where T: RangeReplaceableCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableBidirectionalSlice<T: MutableCollection> = Slice<T> where T: RangeReplaceableCollection, T: BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableRandomAccessSlice<T: MutableCollection> = Slice<T> where T: RangeReplaceableCollection, T: RandomAccessCollection
+
 
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index a7f31e5..0c42e4b 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,41 @@
     }
     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 +479,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
@@ -600,20 +506,8 @@
       _preconditionFailure("Incrementing past end index")
     }
   }
-
-  // FIXME(ABI)#175 (Type checker)
-  @_inlineable
-  public // WORKAROUND: needed because of rdar://25584401
-  var indices: DefaultRandomAccessIndices<${Self}> {
-    return DefaultRandomAccessIndices(
-      _elements: self,
-      startIndex: self.startIndex,
-      endIndex: self.endIndex)
-  }
-
 }
-
-% end
+#endif
 
 /// Returns the sequence of values (`self`, `self + stride`, `self +
 /// 2 * stride`, ... *last*) where *last* is the last value in the
@@ -626,4 +520,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..bd683fc 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
@@ -397,7 +412,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 +552,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 +689,7 @@
   }
 }
 
-extension String.CharacterView : RangeReplaceableCollection {
+extension String._CharacterView : RangeReplaceableCollection {
   /// Creates an empty character view.
   @_inlineable // FIXME(sil-serialize-all)
   public init() {
@@ -757,7 +772,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 +787,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..957cd46 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -16,7 +16,7 @@
   ///
   /// 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 IndexDistance = _CharacterView.IndexDistance
 
   public typealias SubSequence = Substring
 
@@ -62,7 +62,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 +80,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 +96,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.
@@ -129,7 +129,7 @@
   /// - 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)
+    return _characters.index(i, offsetBy: n)
   }
 
   /// Returns an index that is the specified distance from the given index,
@@ -173,7 +173,7 @@
   public func index(
     _ i: Index, offsetBy n: IndexDistance, 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.
@@ -187,7 +187,7 @@
   /// - 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)
+    return _characters.distance(from: start, to: end)
   }
 
   /// Accesses the character at the given position.
@@ -206,7 +206,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 +228,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 +246,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 +263,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 +274,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 +298,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 +317,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 +340,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 +366,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 +383,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 +399,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/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 8c0f007..38d4d63 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -94,17 +94,17 @@
   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 +116,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)
@@ -434,7 +434,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 +446,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 +537,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 +661,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 +712,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..068e0bc 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 {
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..2dd8af6 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -251,12 +251,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 +352,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 +381,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 bb7aeb9..f437211 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..674e108 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,105 @@
     }
   }
 
+  /// 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 IndexDistance = 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 +483,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 +510,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 +524,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 +654,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..b516382 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)
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..56ae09c 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
@@ -69,14 +66,12 @@
 
 # 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-ELF.cpp
     ${swift_runtime_sources}
     ${swift_runtime_objc_sources}
     ${swift_runtime_leaks_sources})
@@ -92,14 +87,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 +94,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
@@ -147,111 +130,48 @@
 set(ELFISH_SDKS)
 foreach(sdk ${SWIFT_CONFIGURED_SDKS})
   if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF")
-    list(APPEND ELFISH_SDKS "${sdk}")
+    list(APPEND ELFISH_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(swiftImageRegistrationObject
+                  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)
 
-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")
+      # TODO(compnerd) switch to the generator expression when cmake is upgraded
+      # to a version which supports it.
+      # set(swiftrtObject "$<TARGET_OBJECTS:swiftImageRegistrationObject-${arch_suffix}>")
+      set(swiftrtObject ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/swiftImageRegistrationObject-${arch_suffix}.dir/SwiftRT-ELF.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..9622bd6 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -113,7 +113,6 @@
   return result;
 }
 
-SWIFT_CC(swift)
 TwoWordPair<const char *, uintptr_t>::Return
 swift::swift_getTypeName(const Metadata *type, bool qualified) {
   using Pair = TwoWordPair<const char *, uintptr_t>;
@@ -2972,9 +2971,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 +3034,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 +3054,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 +3086,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 +3098,7 @@
     
     std::tie(sourceType, sourceBoxedValue) = getValueFromSwiftValue(srcBox);
     if (sourceType == nativeType) {
-      _swift_bridgeNonVerbatimBoxedValue(sourceBoxedValue,
-                                         destValue,
-                                         nativeType);
+      _bridgeNonVerbatimBoxedValue(sourceBoxedValue, destValue, nativeType);
       return true;
     }
   }
@@ -3102,15 +3106,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 +3151,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 +3200,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 +3220,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 +3228,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/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/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/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..a028917 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -273,8 +273,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);
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index fa8ac6a..b86a85d 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.
@@ -1426,9 +1425,9 @@
 
 using ClassExtents = TwoWordPair<size_t, size_t>;
 
-SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 ClassExtents::Return
-swift_class_getInstanceExtents(const Metadata *c) {
+_getSwiftClassInstanceExtents(const Metadata *c) {
   assert(c && c->isClassObject());
   auto metaData = c->getClassObject();
   return ClassExtents{
@@ -1439,15 +1438,14 @@
 
 #if SWIFT_OBJC_INTEROP
 
-SWIFT_CC(swift)
-SWIFT_RUNTIME_EXPORT
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 ClassExtents::Return
-swift_objc_class_unknownGetInstanceExtents(const ClassMetadata* c) {
+_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-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/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/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 0c1fedf..7b6f025 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -64,6 +64,8 @@
 #define strtod_l swift_strtod_l
 #define strtof_l swift_strtof_l
 #define strtold_l swift_strtold_l
+#elif defined(__linux__)
+#include <locale.h>
 #else
 #include <xlocale.h>
 #endif
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/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index 51a6692..33bf9fd 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -32,7 +32,7 @@
 func extensionMethods(b b: B) {
   // CHECK:      load i8*, i8** @"\01L_selector(method:separateExtMethod:)", align 8
   // CHECK:      [[T0:%.*]] = call i8* bitcast (void ()* @objc_msgSend to i8*
-  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+  // CHECK-NEXT: [[T1:%.*]] = {{.*}}call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
   // CHECK-NOT:  [[T0]]
   // CHECK:      [[T1]]
   b.method(1, separateExtMethod:1.5)
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/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..dd4c30a 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 'String.IndexDistance' (aka '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/diagnostics_swift4.swift b/test/Constraints/diagnostics_swift4.swift
index 9571efc..fa2917f 100644
--- a/test/Constraints/diagnostics_swift4.swift
+++ b/test/Constraints/diagnostics_swift4.swift
@@ -54,4 +54,5 @@
 infix operator +=+ : AdditionPrecedence
 func +=+(_ lhs: Int, _ rhs: Int) -> Bool { return lhs == rhs }
 func +=+<T: BinaryInteger>(_ lhs: T, _ rhs: Int) -> Bool { return lhs == rhs }
-let _ = DoubleWidth<Int>(Int.min) - 1 +=+ Int.min // Ok
+// FIXME: uncomment when <rdar://problem/32726173> is resolved and DoubleWidth is back
+// let _ = DoubleWidth<Int>(Int.min) - 1 +=+ Int.min // Ok
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/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/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/linetable-cleanups.swift b/test/DebugInfo/linetable-cleanups.swift
index bdece07..278775f 100644
--- a/test/DebugInfo/linetable-cleanups.swift
+++ b/test/DebugInfo/linetable-cleanups.swift
@@ -20,10 +20,10 @@
 // CHECK: call {{.*}}void @_T04main8markUsedyxlF
 // CHECK: br label
 // CHECK: <label>:
-// CHECK: call %Ts16IndexingIteratorVySaySiGG* @_T0s16IndexingIteratorVySaySiGGWh0_(%Ts16IndexingIteratorVySaySiGG* %"$element$generator"), !dbg ![[LOOPHEADER_LOC:.*]]
+// CHECK: call %Ts16IndexingIteratorVySaySiGG* @_T0s16IndexingIteratorVySaySiGGWh0_(%Ts16IndexingIteratorVySaySiGG* %{{.*}}), !dbg ![[LOOPHEADER_LOC:.*]]
 // CHECK: call {{.*}}void @_T04main8markUsedyxlF
 // The cleanups should share the line number with the ret stmt.
-// CHECK:  call %TSa* @_T0SaySiGWh0_(%TSa* %b), !dbg ![[CLEANUPS:.*]]
+// CHECK:  call %TSa* @_T0SaySiGWh0_(%TSa* %{{.*}}), !dbg ![[CLEANUPS:.*]]
 // CHECK-NEXT:  !dbg ![[CLEANUPS]]
 // CHECK-NEXT:  llvm.lifetime.end
 // CHECK-NEXT:  load
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/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/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 6ac0a6c..b1a9e00 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 {}
@@ -323,3 +323,14 @@
 // CHECK-NEXT:   conforms_to: τ_0_0 P1
 // CHECK-NEXT:   same_type: τ_0_0 τ_0_1)
 extension RedundancyOrderDependenceBad: P2 where T: P1, T == U {}
+
+// Checking of conditional requirements for existential conversions.
+func existential_good<T: P1>(_: T.Type) {
+  _ = Free<T>() as P2
+}
+
+func existential_bad<T>(_: T.Type) {
+  // FIXME: Poor diagnostic.
+  _ = Free<T>() as P2 // expected-error{{'Free<T>' is not convertible to 'P2'; did you mean to use 'as!' to force downcast?}}
+}
+
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/IDE/complete_from_clang_framework_typechecker.swift b/test/IDE/complete_from_clang_framework_typechecker.swift
index a7e9137..149811a 100644
--- a/test/IDE/complete_from_clang_framework_typechecker.swift
+++ b/test/IDE/complete_from_clang_framework_typechecker.swift
@@ -1,6 +1,6 @@
 // RUN: %target-typecheck-verify-swift -F %S/Inputs/mock-sdk
 
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 import Foo
 // Don't import 'FooHelper'.
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_ast_overlay.swift b/test/IDE/print_ast_overlay.swift
index cd022b4..7a60b6c 100644
--- a/test/IDE/print_ast_overlay.swift
+++ b/test/IDE/print_ast_overlay.swift
@@ -8,7 +8,7 @@
 // RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo.FooSub > %t.printed.txt
 // RUN: %FileCheck %s -check-prefix=PASS_WITHOUT_OVERLAY -strict-whitespace < %t.printed.txt
 
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 // RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo -access-filter-public -annotate-print > %t.annotated.txt
 // RUN: %FileCheck %s -check-prefix=PASS_ANNOTATED -strict-whitespace < %t.annotated.txt
diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift
index 88100f1..f8f5215 100644
--- a/test/IDE/print_ast_tc_decls.swift
+++ b/test/IDE/print_ast_tc_decls.swift
@@ -58,7 +58,7 @@
 // FIXME: %FileCheck %s -check-prefix=PASS_EXPLODE_PATTERN -strict-whitespace < %t.printed.txt
 
 // FIXME: rdar://problem/19648117 Needs splitting objc parts out
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 import Bar
 import ObjectiveC
diff --git a/test/IDE/print_clang_decls.swift b/test/IDE/print_clang_decls.swift
index 40c9b86..1b60290 100644
--- a/test/IDE/print_clang_decls.swift
+++ b/test/IDE/print_clang_decls.swift
@@ -1,6 +1,6 @@
 // RUN: %empty-directory(%t)
 
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 // This file deliberately does not use %clang-importer-sdk for most RUN lines.
 // Instead, it generates custom overlay modules itself, and uses -I %t when it
diff --git a/test/IDE/print_clang_header.swift b/test/IDE/print_clang_header.swift
index c321a54..2faccf8 100644
--- a/test/IDE/print_clang_header.swift
+++ b/test/IDE/print_clang_header.swift
@@ -1,5 +1,5 @@
 // FIXME: rdar://problem/19648117 Needs splitting objc parts out
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 // RUN: echo '#include "header-to-print.h"' > %t.m
 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.m -I %S/Inputs/print_clang_header > %t.txt
diff --git a/test/IDE/print_clang_header_i386.swift b/test/IDE/print_clang_header_i386.swift
index c147acc..5f51418 100644
--- a/test/IDE/print_clang_header_i386.swift
+++ b/test/IDE/print_clang_header_i386.swift
@@ -1,6 +1,6 @@
 // REQUIRES: OS=macosx
 // FIXME: rdar://problem/19648117 Needs splitting objc parts out
-// XFAIL: linux
+// XFAIL: linux, freebsd
 
 // RUN: echo '#include "header-to-print.h"' > %t.i386.m
 // RUN: %target-swift-ide-test -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args -arch i386 -isysroot %clang-importer-sdk-path -fsyntax-only %t.i386.m -I %S/Inputs/print_clang_header > %t.i386.txt
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/autorelease.sil b/test/IRGen/autorelease.sil
index fe066ff..74f7b6e 100644
--- a/test/IRGen/autorelease.sil
+++ b/test/IRGen/autorelease.sil
@@ -58,7 +58,7 @@
 // x86_64:    define{{( protected)?}} swiftcc i64 @bar(i64)
 // x86_64:      [[T0:%.*]] = call swiftcc i64 @foo(i64 %0)
 // x86_64-NEXT: [[T1:%.*]] = inttoptr i64 [[T0]] to i8*
-// x86_64-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// x86_64-NEXT: [[T2:%.*]] = notail call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
 // x86_64-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i64
 // x86_64-NEXT: ret i64 [[T3]]
 
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/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..c90670e 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 %swift.type* @swift_initClassMetadata_UniversalStrategy
+
+// CHECK-V3-LABEL: define private void @initialize_metadata_SubSubButtHolder
+// CHECK-V3:   call %swift.type* @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_retainAutoreleasedReturnValue.swift b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
new file mode 100644
index 0000000..98a9ed3
--- /dev/null
+++ b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
@@ -0,0 +1,37 @@
+// RUN: %target-swift-frontend -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend -O -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s --check-prefix=OPT
+
+// REQUIRES: objc_interop
+// REQUIRES: CPU=x86_64
+// REQUIRES: OS=macosx
+import Foundation
+
+@inline(never)
+public func useClosure(_ dict: NSDictionary, _ action : (NSDictionary) -> ()) {
+  action(dict)
+}
+
+@inline(never)
+public func test(_ dict: NSDictionary) {
+  useClosure(dict, { $0.objectEnumerator()} )
+}
+
+//  Don't tail call objc_retainAutoreleasedReturnValue as this would block the
+//  autorelease return value optimization.
+
+// callq  0x01ec08 ; symbol stub for: objc_msgSend
+// movq   %rax, %rdi
+// popq   %rbp  ;<== Blocks the handshake from objc_autoreleaseReturnValue
+// jmp    0x01ec20 ; symbol stub for: objc_retainAutoreleasedReturnValue
+
+// CHECK-LABEL: define {{.*}}swiftcc void @_T034objc_retainAutoreleasedReturnValue4testySo12NSDictionaryCFyADcfU_(%TSo12NSDictionaryC*)
+// CHECK: entry:
+// CHECK:   call {{.*}}@objc_msgSend
+// CHECK:   notail call i8* @objc_retainAutoreleasedReturnValue
+// CHECK:   ret void
+
+// OPT-LABEL: define {{.*}}swiftcc void @_T034objc_retainAutoreleasedReturnValue4testySo12NSDictionaryCFyADcfU_(%TSo12NSDictionaryC*)
+// OPT: entry:
+// OPT:   call {{.*}}@objc_msgSend
+// OPT:   notail call i8* @objc_retainAutoreleasedReturnValue
+// OPT:   ret void
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/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/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 e5b2681..0a839a3 100644
--- a/test/Inputs/conditional_conformance_basic_conformances.swift
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -23,9 +23,6 @@
 // CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
 // CHECK-NEXT:    [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
 // CHECK-NEXT:    [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %0 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
@@ -40,9 +37,6 @@
 // CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
 // CHECK-NEXT:    [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
 // CHECK-NEXT:    [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %1 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
@@ -136,10 +130,6 @@
 // CHECK-NEXT:    [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
 // CHECK-NEXT:    [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
 
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %0 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
-
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
@@ -165,10 +155,6 @@
 // CHECK-NEXT:    [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
 // CHECK-NEXT:    [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
 
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %1 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
-
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
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/Inputs/conditional_conformance_subclass.swift b/test/Inputs/conditional_conformance_subclass.swift
index 96d0525..76f27eb 100644
--- a/test/Inputs/conditional_conformance_subclass.swift
+++ b/test/Inputs/conditional_conformance_subclass.swift
@@ -22,10 +22,7 @@
 // CHECK-NEXT:    [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
 // CHECK-NEXT:    %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
 // CHECK-NEXT:    [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.0*, %T32conditional_conformance_subclass4BaseC.0** %0
-// CHECK-NEXT:    [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.0* [[SELF]] to %swift.refcounted*
-// CHECK-NEXT:    [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
 // CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE6normalyyF(i8** %"\CF\84_0_0.P2", %T32conditional_conformance_subclass4BaseC.0* swiftself [[SELF]])
-// CHECK-NEXT:    call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.0*)*)(%T32conditional_conformance_subclass4BaseC.0* [[SELF]])
 // CHECK-NEXT:    ret void
 // CHECK-NEXT:  }
 
@@ -37,10 +34,7 @@
 // CHECK-NEXT:    [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
 // CHECK-NEXT:    %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
 // CHECK-NEXT:    [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.1*, %T32conditional_conformance_subclass4BaseC.1** %1, align 8
-// CHECK-NEXT:    [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.1* [[SELF]] to %swift.refcounted*
-// CHECK-NEXT:    [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
 // CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE7genericyqd__AA2P3Rd__lF(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1* swiftself [[SELF]])
-// CHECK-NEXT:    call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.1*)*)(%T32conditional_conformance_subclass4BaseC.1* [[SELF]])
 // CHECK-NEXT:    ret void
 // CHECK-NEXT:  }
 
diff --git a/test/Inputs/conditional_conformance_with_assoc.swift b/test/Inputs/conditional_conformance_with_assoc.swift
index 63af461..01336d6 100644
--- a/test/Inputs/conditional_conformance_with_assoc.swift
+++ b/test/Inputs/conditional_conformance_with_assoc.swift
@@ -55,10 +55,6 @@
 // CHECK-NEXT:    [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
 // CHECK-NEXT:    %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
 
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %0 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
-
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
@@ -91,10 +87,6 @@
 // CHECK-NEXT:    [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
 // CHECK-NEXT:    %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
 
-// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
-// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %1 to i8*
-// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
-
 // CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
 // CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
 // CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
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/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..a90f295 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
 
diff --git a/test/Interpreter/conditional_conformances_modules.swift b/test/Interpreter/conditional_conformances_modules.swift
index b5c94ae..806c17a 100644
--- a/test/Interpreter/conditional_conformances_modules.swift
+++ b/test/Interpreter/conditional_conformances_modules.swift
@@ -1,9 +1,8 @@
 // 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
-// FIXME: currently fails due to incorrect modeling of type parameters in inherited conformances.
-// %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 -I%t -L%t -lBasic -lWithAssoc %s -o %t/conditional_conformances_modules -Xlinker -rpath -Xlinker %t
+// 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
 
 // REQUIRES: executable_test
@@ -12,8 +11,7 @@
 
 import Basic
 import WithAssoc
-// FIXME: see above
-// import Subclass
+import Subclass
 
 
 public func basic_single_generic<T: Basic.P2>(_: T.Type) {
@@ -52,8 +50,6 @@
   WithAssoc.takes_p1(WithAssoc.Double<WithAssoc.IsAlsoP2, WithAssoc.IsP3>.self)
 }
 
-/*
-FIXME: see above
 public func subclass_subclassgeneric_generic<T: Subclass.P2>(_: T.Type) {
   Subclass.takes_p1(Subclass.SubclassGeneric<T>.self)
 }
@@ -66,7 +62,6 @@
 public func subclass_subclassgenericconcrete() {
   Subclass.takes_p1(Subclass.SubclassGenericConcrete.self)
 }
-*/
 
 
 basic_single_generic(Basic.IsP2.self)
@@ -82,10 +77,7 @@
 with_assoc_concrete_concrete()
 
 
-/*
-FIXME: see above
 subclass_subclassgeneric_generic(Subclass.IsP2.self)
 subclass_subclassgeneric_concrete()
 subclass_subclassconcrete()
 subclass_subclassgenericconcrete()
-*/
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/tuple-arguments.swift b/test/Migrator/tuple-arguments.swift
index 2f9e2a1..33df8a1 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)) }
 }
 
diff --git a/test/Migrator/tuple-arguments.swift.expected b/test/Migrator/tuple-arguments.swift.expected
index bf51964..f64a3a7 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)) }
 }
 
diff --git a/test/Misc/stats_dir_failure_count.swift b/test/Misc/stats_dir_failure_count.swift
index dbbfb58..4c89f74 100644
--- a/test/Misc/stats_dir_failure_count.swift
+++ b/test/Misc/stats_dir_failure_count.swift
@@ -1,3 +1,4 @@
+// REQUIRES: rdar35537905
 // Check that a failed process-tree emits nonzero failure counters
 // RUN: rm -rf %t && mkdir -p %t
 // RUN: echo zzz >%t/other.swift
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..37a02ac 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,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 < -10' %t/stats-pre %t/stats-post
 
+// REQUIRES: rdar35799113
+
 import NamedLazyMembers
 
 public func test(i: DerivedClass.derivedMemberType1) -> DerivedClass.derivedMemberType1 {
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/Prototypes/Algorithms.swift.gyb b/test/Prototypes/Algorithms.swift.gyb
index e8c2409..8c283b1 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
@@ -51,12 +51,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 {
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/UnicodeDecoders.swift b/test/Prototypes/UnicodeDecoders.swift
index ef9e6cb..8a01ff3 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.
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/errors.swift b/test/SILGen/errors.swift
index 3b22eeb..e735a22 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -231,70 +231,50 @@
 }
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T06errors12DoomedStructVAA0B0A2aDP5checkyyKFTW : $@convention(witness_method: Doomed) (@in_guaranteed DoomedStruct) -> @error Error
-// CHECK:      [[TEMP:%.*]] = alloc_stack $DoomedStruct
-// CHECK:      copy_addr %0 to [initialization] [[TEMP]]
-// CHECK:      [[SELF:%.*]] = load [trivial] [[TEMP]] : $*DoomedStruct
+// CHECK:      [[SELF:%.*]] = load [trivial] %0 : $*DoomedStruct
 // CHECK:      [[T0:%.*]] = function_ref @_T06errors12DoomedStructV5checkyyKF : $@convention(method) (DoomedStruct) -> @error Error
 // CHECK-NEXT: try_apply [[T0]]([[SELF]])
 // CHECK:    bb1([[T0:%.*]] : @trivial $()):
 // CHECK:      [[T0:%.*]] = tuple ()
-// CHECK:      dealloc_stack [[TEMP]]
 // CHECK:      return [[T0]] : $()
 // CHECK:    bb2([[T0:%.*]] : @owned $Error):
 // CHECK:      builtin "willThrow"([[T0]] : $Error)
-// CHECK:      dealloc_stack [[TEMP]]
 // CHECK:      throw [[T0]] : $Error
 struct DoomedStruct : Doomed {
   func check() throws {}
 }
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T06errors11DoomedClassCAA0B0A2aDP5checkyyKFTW : $@convention(witness_method: Doomed) (@in_guaranteed DoomedClass) -> @error Error {
-// CHECK:      [[TEMP:%.*]] = alloc_stack $DoomedClass
-// CHECK:      copy_addr %0 to [initialization] [[TEMP]]
-// CHECK:      [[SELF:%.*]] = load [take] [[TEMP]] : $*DoomedClass
-// CHECK:      [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+// CHECK:      [[BORROWED_SELF:%.*]] = load_borrow %0
 // CHECK:      [[T0:%.*]] = class_method [[BORROWED_SELF]] : $DoomedClass, #DoomedClass.check!1 : (DoomedClass) -> () throws -> (), $@convention(method) (@guaranteed DoomedClass) -> @error Error
 // CHECK-NEXT: try_apply [[T0]]([[BORROWED_SELF]])
 // CHECK:    bb1([[T0:%.*]] : @trivial $()):
 // CHECK:      [[T0:%.*]] = tuple ()
-// CHECK:      end_borrow [[BORROWED_SELF]] from [[SELF]]
-// CHECK:      destroy_value [[SELF]] : $DoomedClass
-// CHECK:      dealloc_stack [[TEMP]]
+// CHECK:      end_borrow [[BORROWED_SELF]] from %0
 // CHECK:      return [[T0]] : $()
 // CHECK:    bb2([[T0:%.*]] : @owned $Error):
 // CHECK:      builtin "willThrow"([[T0]] : $Error)
-// CHECK:      end_borrow [[BORROWED_SELF]] from [[SELF]]
-// CHECK:      destroy_value [[SELF]] : $DoomedClass
-// CHECK:      dealloc_stack [[TEMP]]
+// CHECK:      end_borrow [[BORROWED_SELF]] from %0
 // CHECK:      throw [[T0]] : $Error
 class DoomedClass : Doomed {
   func check() throws {}
 }
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T06errors11HappyStructVAA6DoomedA2aDP5checkyyKFTW : $@convention(witness_method: Doomed) (@in_guaranteed HappyStruct) -> @error Error
-// CHECK:      [[TEMP:%.*]] = alloc_stack $HappyStruct
-// CHECK:      copy_addr %0 to [initialization] [[TEMP]]
-// CHECK:      [[SELF:%.*]] = load [trivial] [[TEMP]] : $*HappyStruct
 // CHECK:      [[T0:%.*]] = function_ref @_T06errors11HappyStructV5checkyyF : $@convention(method) (HappyStruct) -> ()
-// CHECK:      [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK:      [[T1:%.*]] = apply [[T0]](%1)
 // CHECK:      [[T1:%.*]] = tuple ()
-// CHECK:      dealloc_stack [[TEMP]]
 // CHECK:      return [[T1]] : $()
 struct HappyStruct : Doomed {
   func check() {}
 }
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T06errors10HappyClassCAA6DoomedA2aDP5checkyyKFTW : $@convention(witness_method: Doomed) (@in_guaranteed HappyClass) -> @error Error
-// CHECK:      [[TEMP:%.*]] = alloc_stack $HappyClass
-// CHECK:      copy_addr %0 to [initialization] [[TEMP]]
-// CHECK:      [[SELF:%.*]] = load [take] [[TEMP]] : $*HappyClass
-// CHECK:      [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-// CHECK:      [[T0:%.*]] = class_method [[BORROWED_SELF]] : $HappyClass, #HappyClass.check!1 : (HappyClass) -> () -> (), $@convention(method) (@guaranteed HappyClass) -> ()
-// CHECK:      [[T1:%.*]] = apply [[T0]]([[BORROWED_SELF]])
+// CHECK:      [[SELF:%.*]] = load_borrow %0 : $*HappyClass
+// CHECK:      [[T0:%.*]] = class_method [[SELF]] : $HappyClass, #HappyClass.check!1 : (HappyClass) -> () -> (), $@convention(method) (@guaranteed HappyClass) -> ()
+// CHECK:      [[T1:%.*]] = apply [[T0]]([[SELF]])
 // CHECK:      [[T1:%.*]] = tuple ()
-// CHECK:      end_borrow [[BORROWED_SELF]] from [[SELF]]
-// CHECK:      destroy_value [[SELF]] : $HappyClass
-// CHECK:      dealloc_stack [[TEMP]]
+// CHECK:      end_borrow [[SELF]] from %0
 // CHECK:      return [[T1]] : $()
 class HappyClass : Doomed {
   func check() {}
@@ -308,19 +288,13 @@
 }
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Sis5Error_pIgdzo_SisAA_pIgrzo_TR : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error Error)) -> (@out Int, @error Error)
 // CHECK: bb0(%0 : @trivial $*Int, %1 : @guaranteed $@noescape @callee_guaranteed () -> (Int, @error Error)):
-// CHECK:  [[COPY:%.*]] = copy_value %1
-// CHECK:  [[BORROW:%.*]] = begin_borrow [[COPY]] 
-// CHECK:   try_apply [[BORROW]]()
+// CHECK:   try_apply %1()
 // CHECK: bb1([[T0:%.*]] : @trivial $Int):
 // CHECK:   store [[T0]] to [trivial] %0 : $*Int
 // CHECK:   [[T0:%.*]] = tuple ()
-// CHECK:   end_borrow [[BORROW]]
-// CHECK:   destroy_value [[COPY]]
 // CHECK:   return [[T0]]
 // CHECK: bb2([[T0:%.*]] : @owned $Error):
 // CHECK:   builtin "willThrow"([[T0]] : $Error)
-// CHECK:   end_borrow [[BORROW]]
-// CHECK:   destroy_value [[COPY]]
 // CHECK:   throw [[T0]] : $Error
 
 func createInt(_ fn: () -> Int) throws {}
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 864c4f4..e08a19b4 100644
--- a/test/SILGen/function_conversion.swift
+++ b/test/SILGen/function_conversion.swift
@@ -133,22 +133,14 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion7TrivialVSgACIegyd_AcDIegyd_TR : $@convention(thin) (Trivial, @guaranteed @callee_guaranteed (Optional<Trivial>) -> Trivial) -> Optional<Trivial>
-// CHECK:    [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    [[ENUM:%.*]] = enum $Optional<Trivial>
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[ENUM]])
+// CHECK:         [[ENUM:%.*]] = enum $Optional<Trivial>
+// CHECK-NEXT:    apply %1([[ENUM]])
 // CHECK-NEXT:    enum $Optional<Trivial>
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion7TrivialVSgACIegyd_A2DIegyd_TR : $@convention(thin) (Optional<Trivial>, @guaranteed @callee_guaranteed (Optional<Trivial>) -> Trivial) -> Optional<Trivial>
-// CHECK:    [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]](%0)
+// CHECK:         apply %1(%0)
 // CHECK-NEXT:    enum $Optional<Trivial>
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil hidden @_T019function_conversion20convOptionalLoadableyAA0E0VADSgcF
@@ -163,12 +155,8 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion8LoadableVSgACIegxo_A2DIegxo_TR : $@convention(thin) (@owned Optional<Loadable>, @guaranteed @callee_guaranteed (@owned Optional<Loadable>) -> @owned Loadable) -> @owned Optional<Loadable>
-// CHECK:    [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]](%0)
+// CHECK:         apply %1(%0)
 // CHECK-NEXT:    enum $Optional<Loadable>
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil hidden @_T019function_conversion20convOptionalAddrOnlyyAA0eF0VADSgcF
@@ -179,17 +167,13 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion8AddrOnlyVSgACIegir_A2DIegir_TR : $@convention(thin) (@in Optional<AddrOnly>, @guaranteed @callee_guaranteed (@in Optional<AddrOnly>) -> @out AddrOnly) -> @out Optional<AddrOnly>
-// CHECK:    [[COPY:%.*]] = copy_value %2
-// CHECK-NEXT:    [[TEMP:%.*]] = alloc_stack $AddrOnly
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[TEMP]], %1)
+// CHECK:         [[TEMP:%.*]] = alloc_stack $AddrOnly
+// CHECK-NEXT:    apply %2([[TEMP]], %1)
 // CHECK-NEXT:    init_enum_data_addr %0 : $*Optional<AddrOnly>
 // CHECK-NEXT:    copy_addr [take] {{.*}} to [initialization] {{.*}} : $*AddrOnly
 // CHECK-NEXT:    inject_enum_addr %0 : $*Optional<AddrOnly>
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow
 // CHECK-NEXT:    dealloc_stack {{.*}} : $*AddrOnly
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // ==== Existentials
@@ -223,11 +207,9 @@
 // CHECK:         alloc_stack $Q
 // CHECK-NEXT:    init_existential_addr
 // CHECK-NEXT:    store
-// CHECK-NEXT:    begin_borrow
 // CHECK-NEXT:    apply
 // CHECK-NEXT:    init_existential_addr
 // CHECK-NEXT:    store
-// CHECK:         end_borrow
 // CHECK:         return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion1Q_pSgAA7TrivialVIegid_AESgAA1P_pIegyr_TR
@@ -250,11 +232,9 @@
 // CHECK-NEXT:    open_existential_addr immutable_access %1 : $*P
 // CHECK-NEXT:    init_existential_addr [[TMP]] : $*Q
 // CHECK-NEXT:    copy_addr {{.*}} to [initialization] {{.*}}
-// CHECK-NEXT:    begin_borrow
 // CHECK-NEXT:    apply
 // CHECK-NEXT:    init_existential_addr
 // CHECK-NEXT:    store
-// CHECK:         end_borrow
 // CHECK:         destroy_addr
 // CHECK:         return
 
@@ -276,16 +256,12 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtAA1P_pXmTIegyd_TR : $@convention(thin) (@thin Trivial.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
-// CHECK:         [[ARGCOPY:%.*]] = copy_value
-// CHECK-NEXT:    [[META:%.*]] = metatype $@thick Trivial.Type
+// CHECK:         [[META:%.*]] = metatype $@thick Trivial.Type
 // CHECK-NEXT:    init_existential_metatype [[META]] : $@thick Trivial.Type, $@thick Q.Type
 // CHECK-NEXT:    enum $Optional<@thick Q.Type>
-// CHECK-NEXT:     begin_borrow
 // CHECK-NEXT:    apply
 // CHECK-NEXT:    metatype $@thick Trivial.Type
 // CHECK-NEXT:    init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
-// CHECK-NEXT:    end_borrow
-// CHECK-NEXT:    destroy_value [[ARGCOPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtSgAA1P_pXmTIegyd_TR : $@convention(thin) (Optional<@thin Trivial.Type>, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
@@ -297,25 +273,18 @@
 // CHECK: bb2:
 // CHECK-NEXT:    enum $Optional<@thick Q.Type>
 // CHECK: bb3({{.*}}):
-// CHECK-NEXT:    begin_borrow
 // CHECK-NEXT:    apply
 // CHECK-NEXT:    metatype $@thick Trivial.Type
 // CHECK-NEXT:    init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
-// CHECK-NEXT:    end_borrow
-// CHECK-NEXT:    destroy_value
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AA1P_pXmTAaF_pXmTIegyd_TR : $@convention(thin) (@thick P.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
-// CHECK:         copy_value
-// CHECK-NEXT:    open_existential_metatype %0 : $@thick P.Type to $@thick (@opened({{.*}}) P).Type
-// CHECK-NEXT:    init_existential_metatype %3 : $@thick (@opened({{.*}}) P).Type, $@thick Q.Type
+// CHECK:         open_existential_metatype %0 : $@thick P.Type to $@thick (@opened({{.*}}) P).Type
+// CHECK-NEXT:    init_existential_metatype %2 : $@thick (@opened({{.*}}) P).Type, $@thick Q.Type
 // CHECK-NEXT:    enum $Optional<@thick Q.Type>
-// CHECK-NEXT:    begin_borrow
-// CHECK-NEXT:    apply
+// CHECK-NEXT:    apply %1
 // CHECK-NEXT:    metatype $@thick Trivial.Type
 // CHECK-NEXT:    init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
-// CHECK-NEXT:    end_borrow
-// CHECK-NEXT:    destroy_value
 // CHECK-NEXT:    return
 
 // ==== Class metatype upcasts
@@ -379,14 +348,12 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0ypS2iIegyd_Iegio_S2iIgyd_ypIegxr_TR : $@convention(thin) (@owned @noescape @callee_guaranteed (Int) -> Int, @guaranteed @callee_guaranteed (@in Any) -> @owned @callee_guaranteed (Int) -> Int) -> @out Any
-// CHECK:         copy_value
 // CHECK:         alloc_stack $Any
 // CHECK:         function_ref @_T0S2iIgyd_S2iIgir_TR
 // CHECK-NEXT:    partial_apply
 // CHECK-NEXT:    convert_function
-// CHECK-NEXT:    init_existential_addr %4 : $*Any, $(Int) -> Int
+// CHECK-NEXT:    init_existential_addr %3 : $*Any, $(Int) -> Int
 // CHECK-NEXT:    store
-// CHECK-NEXT:    begin_borrow
 // CHECK-NEXT:    apply
 // CHECK:         function_ref @_T0S2iIegyd_S2iIegir_TR
 // CHECK-NEXT:    partial_apply
@@ -395,14 +362,10 @@
 // CHECK:         return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0S2iIegyd_S2iIegir_TR : $@convention(thin) (@in Int, @guaranteed @callee_guaranteed (Int) -> Int) -> @out Int
-// CHECK:         [[COPY:%.*]] = copy_value %2
-// CHECK-NEXT:    [[LOADED:%.*]] = load [trivial] %1 : $*Int
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[LOADED]])
+// CHECK:         [[LOADED:%.*]] = load [trivial] %1 : $*Int
+// CHECK-NEXT:    apply %2([[LOADED]])
 // CHECK-NEXT:    store {{.*}} to [trivial] %0
 // CHECK-NEXT:    [[VOID:%.*]] = tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK:         return [[VOID]]
 
 // ==== Class-bound archetype upcast
@@ -416,15 +379,12 @@
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion6ParentCxAA7TrivialVIegxod_xAcESgIegxod_ACRbzlTR : $@convention(thin) <T where T : Parent> (@owned T, @guaranteed @callee_guaranteed (@owned Parent) -> (@owned T, Trivial)) -> (@owned Parent, Optional<Trivial>)
 // CHECK: bb0([[ARG:%.*]] : @owned $T, [[CLOSURE:%.*]] : @guaranteed $@callee_guaranteed (@owned Parent) -> (@owned T, Trivial)):
-// CHECK:    [[COPY:%.*]] = copy_value [[CLOSURE]]
 // CHECK:    [[CASTED_ARG:%.*]] = upcast [[ARG]] : $T to $Parent
-// CHECK:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:    [[RESULT:%.*]] = apply [[BORROW]]([[CASTED_ARG]])
+// CHECK:    [[RESULT:%.*]] = apply %1([[CASTED_ARG]])
 // CHECK:    [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]] : $(T, Trivial)
 // CHECK:    [[FIRST_RESULT:%.*]] = tuple_extract [[BORROWED_RESULT]] : $(T, Trivial), 0
 // CHECK:    [[COPIED_FIRST_RESULT:%.*]] = copy_value [[FIRST_RESULT]]
 // CHECK:    tuple_extract [[BORROWED_RESULT]] : $(T, Trivial), 1
-// CHECK:    end_borrow [[BORROWED_RESULT]] from [[RESULT]]
 // CHECK:    destroy_value [[RESULT]]
 // CHECK:    [[CAST_COPIED_FIRST_RESULT:%.*]] = upcast [[COPIED_FIRST_RESULT]] : $T to $Parent
 // CHECK:    enum $Optional<Trivial>
@@ -439,17 +399,13 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T019function_conversion6ParentCXMTxXMTAA7TrivialVIegydd_xXMTACXMTAESgIegydd_ACRbzlTR : $@convention(thin) <T where T : Parent> (@thick T.Type, @guaranteed @callee_guaranteed (@thick Parent.Type) -> (@thick T.Type, Trivial)) -> (@thick Parent.Type, Optional<Trivial>)
-// CHECK:         copy_value
 // CHECK:         upcast %0 : $@thick T.Type to $@thick Parent.Type
-// CHECK-NEXT:    begin_borrow
 // CHECK-NEXT:    apply
 // CHECK-NEXT:    tuple_extract
 // CHECK-NEXT:    tuple_extract
 // CHECK-NEXT:    upcast {{.*}} : $@thick T.Type to $@thick Parent.Type
 // CHECK-NEXT:    enum $Optional<Trivial>
 // CHECK-NEXT:    tuple
-// CHECK-NEXT:    end_borrow
-// CHECK-NEXT:    destroy_value
 // CHECK-NEXT:    return
 
 // ==== Make sure we destructure one-element tuples
@@ -487,15 +443,11 @@
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0S3iIegydd_S2i_SitSgIegyd_TR : $@convention(thin) (Int, @guaranteed @callee_guaranteed (Int) -> (Int, Int)) -> Optional<(Int, Int)>
 // CHECK:         bb0(%0 : @trivial $Int, %1 : @guaranteed $@callee_guaranteed (Int) -> (Int, Int)):
-// CHECK:           [[COPY:%.*]] = copy_value %1
-// CHECK:           [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:           [[RESULT:%.*]] = apply [[BORROW]](%0)
+// CHECK:           [[RESULT:%.*]] = apply %1(%0)
 // CHECK-NEXT:      [[LEFT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:      [[RIGHT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:      [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Int)
 // CHECK-NEXT:      [[OPTIONAL:%.*]] = enum $Optional<(Int, Int)>, #Optional.some!enumelt.1, [[RESULT]]
-// CHECK-NEXT:      end_borrow [[BORROW]]
-// CHECK-NEXT:      destroy_value [[COPY]]
 // CHECK-NEXT:      return [[OPTIONAL]]
 
 func convTupleToOptionalDirect(_ f: @escaping (Int) -> (Int, Int)) -> (Int) -> (Int, Int)? {
@@ -514,16 +466,12 @@
 
 // CHECK:       sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xxxIegirr_xx_xtSgIegir_lTR : $@convention(thin) <T> (@in T, @guaranteed @callee_guaranteed (@in T) -> (@out T, @out T)) -> @out Optional<(T, T)>
 // CHECK:       bb0(%0 : @trivial $*Optional<(T, T)>, %1 : @trivial $*T, %2 : @guaranteed $@callee_guaranteed (@in T) -> (@out T, @out T)):
-// CHECK:         [[COPY:%.*]] = copy_value %2
 // CHECK:         [[OPTIONAL:%.*]] = init_enum_data_addr %0 : $*Optional<(T, T)>, #Optional.some!enumelt.1
 // CHECK-NEXT:    [[LEFT:%.*]] = tuple_element_addr [[OPTIONAL]] : $*(T, T), 0
 // CHECK-NEXT:    [[RIGHT:%.*]] = tuple_element_addr [[OPTIONAL]] : $*(T, T), 1
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[LEFT]], [[RIGHT]], %1)
+// CHECK-NEXT:    apply %2([[LEFT]], [[RIGHT]], %1)
 // CHECK-NEXT:    inject_enum_addr %0 : $*Optional<(T, T)>, #Optional.some!enumelt.1
 // CHECK-NEXT:    [[VOID:%.*]] = tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK:         return [[VOID]]
 
 func convTupleToOptionalIndirect<T>(_ f: @escaping (T) -> (T, T)) -> (T) -> (T, T)? {
@@ -583,79 +531,58 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ieg_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Any
-// CHECK:         [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    init_existential_addr %0 : $*Any, $()
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]()
+// CHECK:         init_existential_addr %0 : $*Any, $()
+// CHECK-NEXT:    apply %1()
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ieg_ypSgIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Optional<Any>
-// CHECK:         [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    [[ENUM_PAYLOAD:%.*]] = init_enum_data_addr %0 : $*Optional<Any>, #Optional.some!enumelt.1
+// CHECK:         [[ENUM_PAYLOAD:%.*]] = init_enum_data_addr %0 : $*Optional<Any>, #Optional.some!enumelt.1
 // CHECK-NEXT:    init_existential_addr [[ENUM_PAYLOAD]] : $*Any, $()
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]()
+// CHECK-NEXT:    apply %1()
 // CHECK-NEXT:    inject_enum_addr %0 : $*Optional<Any>, #Optional.some!enumelt.1
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0S2iIegdd_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Any
-// CHECK:         [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:    [[ANY_PAYLOAD:%.*]] = init_existential_addr %0
+// CHECK:         [[ANY_PAYLOAD:%.*]] = init_existential_addr %0
 // CHECK-NEXT:    [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
 // CHECK-NEXT:    [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    [[RESULT:%.*]] = apply [[BORROW]]()
+// CHECK-NEXT:    [[RESULT:%.*]] = apply %1()
 // CHECK-NEXT:    [[LEFT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:    [[RIGHT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:    store [[LEFT:%.*]] to [trivial] [[LEFT_ADDR]]
 // CHECK-NEXT:    store [[RIGHT:%.*]] to [trivial] [[RIGHT_ADDR]]
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0S2iIegdd_ypSgIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Optional<Any> {
-// CHECK:         [[COPY:%.*]] = copy_value %1
 // CHECK:         [[OPTIONAL_PAYLOAD:%.*]] = init_enum_data_addr %0
 // CHECK-NEXT:    [[ANY_PAYLOAD:%.*]] = init_existential_addr [[OPTIONAL_PAYLOAD]]
 // CHECK-NEXT:    [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
 // CHECK-NEXT:    [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    [[RESULT:%.*]] = apply [[BORROW]]()
+// CHECK-NEXT:    [[RESULT:%.*]] = apply %1()
 // CHECK-NEXT:    [[LEFT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:    [[RIGHT:%.*]] = tuple_extract [[RESULT]]
 // CHECK-NEXT:    store [[LEFT:%.*]] to [trivial] [[LEFT_ADDR]]
 // CHECK-NEXT:    store [[RIGHT:%.*]] to [trivial] [[RIGHT_ADDR]]
 // CHECK-NEXT:    inject_enum_addr %0
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0ypIegi_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in Any) -> ()) -> ()
-// CHECK:         [[COPY:%.*]] = copy_value %2
 // CHECK:         [[ANY_VALUE:%.*]] = alloc_stack $Any
 // CHECK-NEXT:    [[ANY_PAYLOAD:%.*]] = init_existential_addr [[ANY_VALUE]]
 // CHECK-NEXT:    [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
 // CHECK-NEXT:    store %0 to [trivial] [[LEFT_ADDR]]
 // CHECK-NEXT:    [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
 // CHECK-NEXT:    store %1 to [trivial] [[RIGHT_ADDR]]
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[ANY_VALUE]])
+// CHECK-NEXT:    apply %2([[ANY_VALUE]])
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
 // CHECK-NEXT:    dealloc_stack [[ANY_VALUE]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0ypSgIegi_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in Optional<Any>) -> ()) -> ()
-// CHECK:         [[COPY:%.*]] = copy_value %2
 // CHECK:         [[ANY_VALUE:%.*]] = alloc_stack $Any
 // CHECK-NEXT:    [[ANY_PAYLOAD:%.*]] = init_existential_addr [[ANY_VALUE]]
 // CHECK-NEXT:    [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
@@ -666,11 +593,8 @@
 // CHECK-NEXT:    [[OPTIONAL_PAYLOAD:%.*]] = init_enum_data_addr [[OPTIONAL_VALUE]]
 // CHECK-NEXT:    copy_addr [take] [[ANY_VALUE]] to [initialization] [[OPTIONAL_PAYLOAD]]
 // CHECK-NEXT:    inject_enum_addr [[OPTIONAL_VALUE]]
-// CHECK-NEXT:    [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[BORROW]]([[OPTIONAL_VALUE]])
+// CHECK-NEXT:    apply %2([[OPTIONAL_VALUE]])
 // CHECK-NEXT:    tuple ()
-// CHECK-NEXT:    end_borrow [[BORROW]]
 // CHECK-NEXT:    dealloc_stack [[OPTIONAL_VALUE]]
 // CHECK-NEXT:    dealloc_stack [[ANY_VALUE]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return
diff --git a/test/SILGen/function_conversion_objc.swift b/test/SILGen/function_conversion_objc.swift
index 7c500f3..a539287 100644
--- a/test/SILGen/function_conversion_objc.swift
+++ b/test/SILGen/function_conversion_objc.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-source-import -emit-silgen -verify | %FileCheck %s
+// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-sil-ownership -enable-source-import -emit-silgen -verify | %FileCheck %s
 
 import Foundation
 
@@ -14,9 +14,7 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0So8NSObjectCABXMTIegxd_AByXlIegxo_TR : $@convention(thin) (@owned NSObject, @guaranteed @callee_guaranteed (@owned NSObject) -> @thick NSObject.Type) -> @owned AnyObject {
-// CHECK:         [[COPY:%.*]] = copy_value %1
-// CHECK:         [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:         apply [[BORROW]](%0)
+// CHECK:         apply %1(%0)
 // CHECK:         thick_to_objc_metatype {{.*}} : $@thick NSObject.Type to $@objc_metatype NSObject.Type
 // CHECK:         objc_metatype_to_object {{.*}} : $@objc_metatype NSObject.Type to $AnyObject
 // CHECK:         return
@@ -31,9 +29,7 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T024function_conversion_objc9NSBurrito_pAaB_pXmTIegxd_AaB_pyXlIegxo_TR : $@convention(thin) (@owned NSBurrito, @guaranteed @callee_guaranteed (@owned NSBurrito) -> @thick NSBurrito.Type) -> @owned AnyObject
-// CHECK:         [[COPY:%.*]] = copy_value %1
-// CHECK:         [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:         apply [[BORROW]](%0)
+// CHECK:         apply %1(%0)
 // CHECK:         thick_to_objc_metatype {{.*}} : $@thick NSBurrito.Type to $@objc_metatype NSBurrito.Type
 // CHECK:         objc_existential_metatype_to_object {{.*}} : $@objc_metatype NSBurrito.Type to $AnyObject
 // CHECK:         return
@@ -46,9 +42,7 @@
 }
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T024function_conversion_objc9NSBurrito_pXMtIegd_So8ProtocolCIego_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @thin NSBurrito.Protocol) -> @owned Protocol
-// CHECK:         [[COPY:%.*]] = copy_value %0
-// CHECK:         [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:         apply [[BORROW]]() : $@callee_guaranteed () -> @thin NSBurrito.Protocol
+// CHECK:         apply %0() : $@callee_guaranteed () -> @thin NSBurrito.Protocol
 // CHECK:         objc_protocol #NSBurrito : $Protocol
 // CHECK:         copy_value
 // CHECK:         return
@@ -65,7 +59,7 @@
 }
 
 // CHECK-LABEL: sil hidden @_T024function_conversion_objc11blockToFuncyycyyXBF : $@convention(thin) (@owned @convention(block) () -> ()) -> @owned @callee_guaranteed () -> ()
-// CHECK: bb0([[ARG:%.*]] : $@convention(block) () -> ()):
+// CHECK: bb0([[ARG:%.*]] : @owned $@convention(block) () -> ()):
 // CHECK:   [[COPIED:%.*]] = copy_block [[ARG]]
 // CHECK:   [[BORROWED_COPIED:%.*]] = begin_borrow [[COPIED]]
 // CHECK:   [[COPIED_2:%.*]] = copy_value [[BORROWED_COPIED]]
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
new file mode 100644
index 0000000..7f32459
--- /dev/null
+++ b/test/SILGen/guaranteed_normal_args.swift
@@ -0,0 +1,101 @@
+// RUN: %target-swift-frontend -parse-as-library -module-name Swift -parse-stdlib -emit-silgen -enable-sil-ownership -enable-guaranteed-normal-arguments %s | %FileCheck %s
+
+// This test checks specific codegen related to normal arguments being passed at
+// +0. Eventually, it should be merged into normal SILGen tests.
+
+/////////////////
+// Fake Stdlib //
+/////////////////
+
+precedencegroup AssignmentPrecedence {
+  assignment: true
+}
+
+enum Optional<T> {
+case none
+case some(T)
+}
+
+class Klass {
+  init() {}
+}
+
+struct Buffer {
+  var k: Klass
+  init(inK: Klass) {
+    k = inK
+  }
+}
+
+typealias AnyObject = Builtin.AnyObject
+
+protocol Protocol {
+  associatedtype AssocType
+  static func useInput(_ input: Builtin.Int32, into processInput: (AssocType) -> ())
+}
+
+///////////
+// Tests //
+///////////
+
+class KlassWithBuffer {
+  var buffer: Buffer
+
+  // Make sure that the allocating init forwards into the initializing init at +1.
+  // CHECK-LABEL: sil hidden @_T0s15KlassWithBufferCABs0A0C3inK_tcfC : $@convention(method) (@owned Klass, @thick KlassWithBuffer.Type) -> @owned KlassWithBuffer {
+  // CHECK: bb0([[ARG:%.*]] : @owned $Klass,
+  // CHECK:   [[INITIALIZING_INIT:%.*]] = function_ref @_T0s15KlassWithBufferCABs0A0C3inK_tcfc : $@convention(method) (@owned Klass, @owned KlassWithBuffer) -> @owned KlassWithBuffer
+  // CHECK:   apply [[INITIALIZING_INIT]]([[ARG]],
+  // CHECK: } // end sil function '_T0s15KlassWithBufferCABs0A0C3inK_tcfC'
+  init(inK: Klass = Klass()) {
+    buffer = Buffer(inK: inK)
+  }
+
+  // This test makes sure that we:
+  //
+  // 1. Are able to propagate a +0 value value buffer.k into a +0 value and that
+  // we then copy that +0 value into a +1 value, before we begin the epilog and
+  // then return that value.
+  // CHECK-LABEL: sil hidden @_T0s15KlassWithBufferC03getC14AsNativeObjectBoyF : $@convention(method) (@guaranteed KlassWithBuffer) -> @owned Builtin.NativeObject {
+  // CHECK: bb0([[SELF:%.*]] : @guaranteed $KlassWithBuffer):
+  // CHECK:   [[BUF_BOX:%.*]] = alloc_stack $Buffer
+  // CHECK:   [[METHOD:%.*]] = class_method [[SELF]] : $KlassWithBuffer, #KlassWithBuffer.buffer!getter.1
+  // CHECK:   [[BUF:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK:   store [[BUF]] to [init] [[BUF_BOX]]
+  // CHECK:   [[GEP:%.*]] = struct_element_addr [[BUF_BOX]] : $*Buffer, #Buffer.k
+  // CHECK:   [[BUF_KLASS:%.*]] = load [copy] [[GEP]]
+  // CHECK:   destroy_addr [[BUF_BOX]]
+  // CHECK:   [[BORROWED_BUF_KLASS:%.*]] = begin_borrow [[BUF_KLASS]]
+  // CHECK:   [[CASTED_BORROWED_BUF_KLASS:%.*]] = unchecked_ref_cast [[BORROWED_BUF_KLASS]]
+  // CHECK:   [[COPY_CASTED_BORROWED_BUF_KLASS:%.*]] = copy_value [[CASTED_BORROWED_BUF_KLASS]]
+  // CHECK:   end_borrow [[BORROWED_BUF_KLASS]]
+  // CHECK:   destroy_value [[BUF_KLASS]]
+  // CHECK:   return [[COPY_CASTED_BORROWED_BUF_KLASS]]
+  // CHECK: } // end sil function '_T0s15KlassWithBufferC03getC14AsNativeObjectBoyF'
+  func getBufferAsNativeObject() -> Builtin.NativeObject {
+    return Builtin.unsafeCastToNativeObject(buffer.k)
+  }
+}
+
+struct StructContainingBridgeObject {
+  var rawValue: Builtin.BridgeObject
+
+  // CHECK-LABEL: sil hidden @_T0s28StructContainingBridgeObjectVAByXl8swiftObj_tcfC : $@convention(method) (@owned AnyObject, @thin StructContainingBridgeObject.Type) -> @owned StructContainingBridgeObject {
+  // CHECK: bb0([[ARG:%.*]] : @owned $AnyObject,
+  // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+  // CHECK:   [[CASTED_ARG:%.*]] = unchecked_ref_cast [[BORROWED_ARG]] : $AnyObject to $Builtin.BridgeObject
+  // CHECK:   [[COPY_CASTED_ARG:%.*]] = copy_value [[CASTED_ARG]]
+  // CHECK:   assign [[COPY_CASTED_ARG]] to
+  // CHECK: } // end sil function '_T0s28StructContainingBridgeObjectVAByXl8swiftObj_tcfC'
+  init(swiftObj: AnyObject) {
+    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/guaranteed_self.swift b/test/SILGen/guaranteed_self.swift
index db83215..e5975f9 100644
--- a/test/SILGen/guaranteed_self.swift
+++ b/test/SILGen/guaranteed_self.swift
@@ -101,12 +101,8 @@
 // Witness thunk for nonmutating 'foo'
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP3foo{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) (Int, @in_guaranteed S) -> () {
 // CHECK:       bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 // Witness thunk for mutating 'bar'
@@ -119,20 +115,16 @@
 // in the implementation
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP3bas{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) (@inout S) -> ()
 // CHECK:       bb0([[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF:%.*]] = load [copy] [[SELF_ADDR]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK:         end_borrow [[SELF]]
 // CHECK-NOT:     destroy_value [[SELF]]
 
 // Witness thunk for prop1 getter
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop1SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
 // CHECK:       bb0([[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
-// CHECK-NOT:     destroy_addr [[SELF_ADDR]]
+// CHECK-NOT:     destroy_value [[SELF]]
 
 // Witness thunk for prop1 setter
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop1SivsTW : $@convention(witness_method: Fooable) (Int, @inout S) -> () {
@@ -147,12 +139,8 @@
 // Witness thunk for prop2 getter
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop2SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
 // CHECK:       bb0([[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 // Witness thunk for prop2 setter
@@ -168,34 +156,22 @@
 // Witness thunk for prop3 getter
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop3SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
 // CHECK:       bb0([[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 // Witness thunk for prop3 nonmutating setter
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop3SivsTW : $@convention(witness_method: Fooable) (Int, @in_guaranteed S) -> ()
 // CHECK:       bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 // Witness thunk for prop3 nonmutating materializeForSet
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self1SVAA7FooableA2aDP5prop3SivmTW : $@convention(witness_method: Fooable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
 // CHECK:       bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
-// CHECK:         [[SELF_COPY:%.*]] = alloc_stack $S
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY]]
-// CHECK:         [[SELF:%.*]] = load [take] [[SELF_COPY]]
-// CHECK:         destroy_value [[SELF]]
+// CHECK:         [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
 // CHECK-NOT:     destroy_value [[SELF]]
-// CHECK-NOT:     destroy_addr [[SELF_COPY]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 // CHECK:       } // end sil function '_T015guaranteed_self1SVAA7FooableA2aDP5prop3SivmTW'
 
@@ -209,7 +185,6 @@
   init() {}
   // CHECK-LABEL: sil hidden @_T015guaranteed_self2AOV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) <T> (Int, @in_guaranteed AO<T>) -> ()
   // CHECK:       bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<T>):
-  // CHECK-NOT:     copy_addr
   // CHECK:         apply {{.*}} [[SELF_ADDR]]
   // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
   // CHECK:       }
@@ -254,20 +229,15 @@
 // Witness for nonmutating 'foo'
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self2AOVyxGAA7FooableA2aEP3foo{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) <τ_0_0> (Int, @in_guaranteed AO<τ_0_0>) -> ()
 // CHECK:       bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<τ_0_0>):
-// TODO: This copy isn't necessary.
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY:%.*]] :
-// CHECK:         apply {{.*}} [[SELF_COPY]]
-// CHECK:         destroy_addr [[SELF_COPY]]
+// CHECK:         apply {{.*}} [[SELF_ADDR]]
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 // Witness for 'bar', which is mutating in protocol but nonmutating in impl
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015guaranteed_self2AOVyxGAA7FooableA2aEP3bar{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) <τ_0_0> (@inout AO<τ_0_0>) -> ()
 // CHECK:       bb0([[SELF_ADDR:%.*]] : @trivial $*AO<τ_0_0>):
-// -- NB: This copy *is* necessary, unless we're willing to assume an inout
+// -- NB: This copy is not necessary, since we're willing to assume an inout
 //        parameter is not mutably aliased.
-// CHECK:         copy_addr [[SELF_ADDR]] to [initialization] [[SELF_COPY:%.*]] :
-// CHECK:         apply {{.*}} [[SELF_COPY]]
-// CHECK:         destroy_addr [[SELF_COPY]]
+// CHECK:         apply {{.*}}([[SELF_ADDR]])
 // CHECK-NOT:     destroy_addr [[SELF_ADDR]]
 
 class C: Fooable, Barrable {
@@ -417,15 +387,13 @@
 // correctly if we are asked to.
 // ----------------------------------------------------------------------------
 
+
 // CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @_T015guaranteed_self9FakeArrayVAA8SequenceA2aDP17_constrainElement{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Sequence) (@in FakeElement, @in_guaranteed FakeArray) -> () {
 // CHECK: bb0([[ARG0_PTR:%.*]] : @trivial $*FakeElement, [[ARG1_PTR:%.*]] : @trivial $*FakeArray):
-// CHECK: [[GUARANTEED_COPY_STACK_SLOT:%.*]] = alloc_stack $FakeArray
-// CHECK: copy_addr [[ARG1_PTR]] to [initialization] [[GUARANTEED_COPY_STACK_SLOT]]
 // CHECK: [[ARG0:%.*]] = load [trivial] [[ARG0_PTR]]
 // CHECK: function_ref (extension in guaranteed_self):guaranteed_self.SequenceDefaults._constrainElement
 // CHECK: [[FUN:%.*]] = function_ref @_{{.*}}
-// CHECK: apply [[FUN]]<FakeArray>([[ARG0]], [[GUARANTEED_COPY_STACK_SLOT]])
-// CHECK: destroy_addr [[GUARANTEED_COPY_STACK_SLOT]]
+// CHECK: apply [[FUN]]<FakeArray>([[ARG0]], [[ARG1_PTR]])
 
 class Z {}
 
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/nested_generics.swift b/test/SILGen/nested_generics.swift
index bf39453..6524e88 100644
--- a/test/SILGen/nested_generics.swift
+++ b/test/SILGen/nested_generics.swift
@@ -227,16 +227,11 @@
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T015nested_generics9OuterRingC05InnerD0Cyx_qd__GAA30ProtocolWithGenericRequirementA2aGP6method1TQz_1UQzqd__tAK1t_AM1uqd__1vtlFTW : $@convention(witness_method: ProtocolWithGenericRequirement) <τ_0_0><τ_1_0><τ_2_0> (@in τ_0_0, @in τ_1_0, @in τ_2_0, @in_guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0) {
 // CHECK: bb0([[T:%[0-9]+]] : @trivial $*τ_0_0, [[U:%[0-9]+]] : @trivial $*τ_1_0, [[V:%[0-9]+]] : @trivial $*τ_2_0, [[TOut:%[0-9]+]] : @trivial $*τ_0_0, [[UOut:%[0-9]+]] : @trivial $*τ_1_0, [[VOut:%[0-9]+]] : @trivial $*τ_2_0, [[SELF:%[0-9]+]] : @trivial $*OuterRing<τ_0_0>.InnerRing<τ_1_0>):
-// CHECK:   [[SELF_COPY:%[0-9]+]] = alloc_stack $OuterRing<τ_0_0>.InnerRing<τ_1_0>
-// CHECK:   copy_addr [[SELF]] to [initialization] [[SELF_COPY]] : $*OuterRing<τ_0_0>.InnerRing<τ_1_0>
-// CHECK:   [[SELF_COPY_VAL:%[0-9]+]] = load [take] [[SELF_COPY]] : $*OuterRing<τ_0_0>.InnerRing<τ_1_0>
-// CHECK:   [[BORROWED_SELF_COPY_VAL:%.*]] = begin_borrow [[SELF_COPY_VAL]]
-// CHECK:   [[METHOD:%[0-9]+]] = class_method [[BORROWED_SELF_COPY_VAL]] : $OuterRing<τ_0_0>.InnerRing<τ_1_0>, #OuterRing.InnerRing.method!1 : <T><U><V> (OuterRing<T>.InnerRing<U>) -> (T, U, V) -> (T, U, V), $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in τ_0_0, @in τ_1_0, @in τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
-// CHECK:   apply [[METHOD]]<τ_0_0, τ_1_0, τ_2_0>([[T]], [[U]], [[V]], [[TOut]], [[UOut]], [[VOut]], [[BORROWED_SELF_COPY_VAL]]) : $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in τ_0_0, @in τ_1_0, @in τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
+// CHECK:   [[SELF_COPY_VAL:%[0-9]+]] = load_borrow [[SELF]] : $*OuterRing<τ_0_0>.InnerRing<τ_1_0>
+// CHECK:   [[METHOD:%[0-9]+]] = class_method [[SELF_COPY_VAL]] : $OuterRing<τ_0_0>.InnerRing<τ_1_0>, #OuterRing.InnerRing.method!1 : <T><U><V> (OuterRing<T>.InnerRing<U>) -> (T, U, V) -> (T, U, V), $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in τ_0_0, @in τ_1_0, @in τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
+// CHECK:   apply [[METHOD]]<τ_0_0, τ_1_0, τ_2_0>([[T]], [[U]], [[V]], [[TOut]], [[UOut]], [[VOut]], [[SELF_COPY_VAL]]) : $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in τ_0_0, @in τ_1_0, @in τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
 // CHECK:   [[RESULT:%[0-9]+]] = tuple ()
-// CHECK:   end_borrow [[BORROWED_SELF_COPY_VAL]] from [[SELF_COPY_VAL]]
-// CHECK:   destroy_value [[SELF_COPY_VAL]] : $OuterRing<τ_0_0>.InnerRing<τ_1_0>
-// CHECK:   dealloc_stack [[SELF_COPY]] : $*OuterRing<τ_0_0>.InnerRing<τ_1_0>
+// CHECK:   end_borrow [[SELF_COPY_VAL]] from [[SELF]]
 // CHECK:   return [[RESULT]] : $()
 
 // CHECK: sil_witness_table hidden <Spices> Deli<Spices>.Pepperoni: CuredMeat module nested_generics {
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/objc_witnesses.swift b/test/SILGen/objc_witnesses.swift
index 456d2ec..130e294 100644
--- a/test/SILGen/objc_witnesses.swift
+++ b/test/SILGen/objc_witnesses.swift
@@ -22,22 +22,13 @@
 // CHECK-LABEL: sil private [transparent] [thunk] @_T0So3FooC14objc_witnesses7FooableA2cDP3foo{{[_0-9a-zA-Z]*}}FTW
 // CHECK:         function_ref @_T0So3FooC3foo{{[_0-9a-zA-Z]*}}FTO
 
-// *NOTE* We have an extra copy here for the time being right
-// now. This will change once we teach SILGen how to not emit the
-// extra copy.
-//
 // witness for Phoûx.foo uses the Swift vtable
 // CHECK-LABEL: _T014objc_witnesses008Phox_xraC3foo{{[_0-9a-zA-Z]*}}F
 // CHECK:      bb0([[IN_ADDR:%.*]] : 
-// CHECK:         [[STACK_SLOT:%.*]] = alloc_stack $Phoûx
-// CHECK:         copy_addr [[IN_ADDR]] to [initialization] [[STACK_SLOT]]
-// CHECK:         [[VALUE:%.*]] = load [take] [[STACK_SLOT]]
-// CHECK:         [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
-// CHECK:         [[CLS_METHOD:%.*]] = class_method [[BORROWED_VALUE]] : $Phoûx, #Phoûx.foo!1
-// CHECK:         apply [[CLS_METHOD]]([[BORROWED_VALUE]])
-// CHECK:         end_borrow [[BORROWED_VALUE]] from [[VALUE]]
-// CHECK:         destroy_value [[VALUE]]
-// CHECK:         dealloc_stack [[STACK_SLOT]]
+// CHECK:         [[VALUE:%.*]] = load_borrow [[IN_ADDR]]
+// CHECK:         [[CLS_METHOD:%.*]] = class_method [[VALUE]] : $Phoûx, #Phoûx.foo!1
+// CHECK:         apply [[CLS_METHOD]]([[VALUE]])
+// CHECK:         end_borrow [[VALUE]] from [[IN_ADDR]]
 
 protocol Bells {
   init(bellsOn: Int)
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index 5dcf735..995142c 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -90,13 +90,8 @@
 // ---
 // CHECK-LABEL: sil private @_T020opaque_values_silgen16OpaqueTupleClassC8inAndOutx_xtx_xt1x_tFAA0dF0CADxxAE_tFTV : $@convention(method) <U> (@in (U, U), @guaranteed OpaqueTupleClass<U>) -> @out (U, U) {
 // CHECK: bb0([[ARG0:%.*]] : $(U, U), [[ARG1:%.*]] : $OpaqueTupleClass<U>):
-// CHECK:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]] : $(U, U)
-// CHECK:   [[TELEM0:%.*]] = tuple_extract [[BORROWED_ARG0]] : $(U, U), 0
-// CHECK:   [[COPY0:%.*]] = copy_value [[TELEM0]] : $U
-// CHECK:   [[TELEM1:%.*]] = tuple_extract [[BORROWED_ARG0]] : $(U, U), 1
-// CHECK:   [[COPY1:%.*]] = copy_value [[TELEM1]] : $U
-// CHECK:   end_borrow [[BORROWED_ARG0]]
-// CHECK:   [[APPLY:%.*]] = apply {{.*}}<U>([[COPY0]], [[COPY1]], [[ARG1]]) : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @guaranteed OpaqueTupleClass<τ_0_0>) -> (@out τ_0_0, @out τ_0_0)
+// CHECK:   ([[TELEM0:%.*]], [[TELEM1:%.*]]) = destructure_tuple [[ARG0]] : $(U, U)
+// CHECK:   [[APPLY:%.*]] = apply {{.*}}<U>([[TELEM0]], [[TELEM1]], [[ARG1]]) : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @guaranteed OpaqueTupleClass<τ_0_0>) -> (@out τ_0_0, @out τ_0_0)
 // CHECK:   [[BORROWED_CALL:%.*]] = begin_borrow [[APPLY]]
 // CHECK:   [[BORROWED_CALL_EXT0:%.*]] = tuple_extract [[BORROWED_CALL]] : $(U, U), 0
 // CHECK:   [[RETVAL0:%.*]] = copy_value [[BORROWED_CALL_EXT0]] : $U
@@ -133,16 +128,12 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T020opaque_values_silgen1P_pAA13TrivialStructVIegid_AA2P2_pAaE_pIegir_TR : $@convention(thin) (@in P2, @guaranteed @callee_guaranteed (@in P) -> TrivialStruct) -> @out P2 {
 // CHECK: bb0([[ARG0:%.*]] : $P2, [[ARG1:%.*]] : $@callee_guaranteed (@in P) -> TrivialStruct):
-// CHECK:   [[FUN_COPY:%.*]] = copy_value [[ARG1]]
 // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG0]] : $P2
 // CHECK:   [[OPENED_ARG:%.*]] = open_existential_value [[BORROWED_ARG]] : $P2 to $@opened({{.*}}) P2
 // CHECK:   [[COPIED_VAL:%.*]] = copy_value [[OPENED_ARG]]
 // CHECK:   [[INIT_P:%.*]] = init_existential_value [[COPIED_VAL]] : $@opened({{.*}}) P2, $@opened({{.*}}) P2, $P
-// CHECK:   [[BORROW:%.*]] = begin_borrow [[FUN_COPY]]
-// CHECK:   [[APPLY_P:%.*]] = apply [[BORROW]]([[INIT_P]]) : $@callee_guaranteed (@in P) -> TrivialStruct
+// CHECK:   [[APPLY_P:%.*]] = apply [[ARG1]]([[INIT_P]]) : $@callee_guaranteed (@in P) -> TrivialStruct
 // CHECK:   [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2
-// CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG0]] : $P2, $P2
-// CHECK:   destroy_value [[FUN_COPY]]
 // CHECK:   destroy_value [[ARG0]]
 // CHECK:   return [[RETVAL]] : $P2
 // CHECK-LABEL: } // end sil function '_T020opaque_values_silgen1P_pAA13TrivialStructVIegid_AA2P2_pAaE_pIegir_TR'
@@ -151,7 +142,6 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T020opaque_values_silgen1P_pSgAA13TrivialStructVIegid_AESgAA2P2_pIegyr_TR : $@convention(thin) (Optional<TrivialStruct>, @guaranteed @callee_guaranteed (@in Optional<P>) -> TrivialStruct) -> @out P2 {
 // CHECK: bb0([[ARG0:%.*]] : $Optional<TrivialStruct>, [[ARG1:%.*]] : $@callee_guaranteed (@in Optional<P>) -> TrivialStruct):
-// CHECK:   [[FUN_COPY:%.*]] = copy_value [[ARG1]]
 // CHECK:   switch_enum [[ARG0]] : $Optional<TrivialStruct>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
 // CHECK: bb1:
 // CHECK:   [[ONONE:%.*]] = enum $Optional<P>, #Optional.none!enumelt
@@ -161,10 +151,8 @@
 // CHECK:   [[ENUM_S:%.*]] = enum $Optional<P>, #Optional.some!enumelt.1, [[INIT_S]] : $P
 // CHECK:   br bb3([[ENUM_S]] : $Optional<P>)
 // CHECK: bb3([[OPT_S:%.*]] : $Optional<P>):
-// CHECK:   [[BORROW:%.*]] = begin_borrow [[FUN_COPY]]
-// CHECK:   [[APPLY_P:%.*]] = apply [[BORROW]]([[OPT_S]]) : $@callee_guaranteed (@in Optional<P>) -> TrivialStruct
+// CHECK:   [[APPLY_P:%.*]] = apply [[ARG1]]([[OPT_S]]) : $@callee_guaranteed (@in Optional<P>) -> TrivialStruct
 // CHECK:   [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2
-// CHECK:   destroy_value [[FUN_COPY]]
 // CHECK:   return [[RETVAL]] : $P2
 // CHECK-LABEL: } // end sil function '_T020opaque_values_silgen1P_pSgAA13TrivialStructVIegid_AESgAA2P2_pIegyr_TR'
 
@@ -901,19 +889,10 @@
 // CHECK:   [[APPLY_T:%.*]] = apply %{{.*}}<((T) -> (), T)>() : $@convention(thin) <τ_0_0> () -> @out Optional<(Int, τ_0_0)>
 // CHECK:   switch_enum [[APPLY_T]] : $Optional<(Int, (@callee_guaranteed (@in T) -> @out (), T))>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
 // CHECK: bb2([[ENUMARG:%.*]] : $(Int, (@callee_guaranteed (@in T) -> @out (), T))):
-// CHECK:   [[BORROWED_ENUMARG:%.*]] = begin_borrow [[ENUMARG]] : $(Int, (@callee_guaranteed (@in T) -> @out (), T))
-// CHECK:   [[TELEM0:%.*]] = tuple_extract [[BORROWED_ENUMARG]] : $(Int, (@callee_guaranteed (@in T) -> @out (), T)), 0
-// CHECK:   [[TELEM1:%.*]] = tuple_extract [[BORROWED_ENUMARG]] : $(Int, (@callee_guaranteed (@in T) -> @out (), T)), 1
-// CHECK:   [[COPY1:%.*]] = copy_value [[TELEM1]] : $(@callee_guaranteed (@in T) -> @out (), T)
-// CHECK:   end_borrow [[BORROWED_ENUMARG]]
-// CHECK:   [[BORROWED_COPY1:%.*]] = begin_borrow [[COPY1]] : $(@callee_guaranteed (@in T) -> @out (), T)
-// CHECK:   [[TELEM1P0:%.*]] = tuple_extract [[BORROWED_COPY1]] : $(@callee_guaranteed (@in T) -> @out (), T), 0
-// CHECK:   [[COPY1P0:%.*]] = copy_value [[TELEM1P0]] : $@callee_guaranteed (@in T) -> @out ()
-// CHECK:   [[TELEM1P1:%.*]] = tuple_extract [[BORROWED_COPY1]] : $(@callee_guaranteed (@in T) -> @out (), T), 1
-// CHECK:   [[COPY1P1:%.*]] = copy_value [[TELEM1P1]] : $T
-// CHECK:   end_borrow [[BORROWED_COPY1]]
-// CHECK:   [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<T>([[COPY1P0]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @out ()) -> ()
-// CHECK:   [[NEWT0:%.*]] = tuple ([[PAPPLY]] : $@callee_guaranteed (@in T) -> (), [[COPY1P1]] : $T)
+// CHECK:   ([[TELEM0:%.*]], [[TELEM1:%.*]]) = destructure_tuple [[ENUMARG]] : $(Int, (@callee_guaranteed (@in T) -> @out (), T))
+// CHECK:   ([[TELEM10:%.*]], [[TELEM11:%.*]]) = destructure_tuple [[TELEM1]] : $(@callee_guaranteed (@in T) -> @out (), T)
+// CHECK:   [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<T>([[TELEM10]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @out ()) -> ()
+// CHECK:   [[NEWT0:%.*]] = tuple ([[PAPPLY]] : $@callee_guaranteed (@in T) -> (), [[TELEM11]] : $T)
 // CHECK:   [[NEWT1:%.*]] = tuple ([[TELEM0]] : $Int, [[NEWT0]] : $(@callee_guaranteed (@in T) -> (), T))
 // CHECK:   [[NEWENUM:%.*]] = enum $Optional<(Int, (@callee_guaranteed (@in T) -> (), T))>, #Optional.some!enumelt.1, [[NEWT1]] : $(Int, (@callee_guaranteed (@in T) -> (), T))
 // CHECK:   br bb3([[NEWENUM]] : $Optional<(Int, (@callee_guaranteed (@in T) -> (), T))>)
@@ -1089,12 +1068,8 @@
 // ---
 // CHECK-LABEL: sil private [transparent] [thunk] @_T020opaque_values_silgen21s510_______OpaqueSelfVyxGAA4FooPA2aEP3fooxyFTW : $@convention(witness_method: FooP) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0> {
 // CHECK: bb0(%0 : $s510_______OpaqueSelf<τ_0_0>):
-// CHECK:   [[COPY:%.*]] = copy_value %0 : $s510_______OpaqueSelf<τ_0_0>
 // CHECK:   [[FN:%.*]] = function_ref @_T020opaque_values_silgen21s510_______OpaqueSelfV3fooACyxGyF : $@convention(method) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0>
-// CHECK:   [[BORROW:%.*]] = begin_borrow [[COPY]] : $s510_______OpaqueSelf<τ_0_0>
-// CHECK:   [[RESULT:%.*]] = apply [[FN]]<τ_0_0>([[BORROW]]) : $@convention(method) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0>
-// CHECK:   end_borrow [[BORROW]] from [[COPY]] : $s510_______OpaqueSelf<τ_0_0>
-// CHECK:   destroy_value [[COPY]] : $s510_______OpaqueSelf<τ_0_0>
+// CHECK:   [[RESULT:%.*]] = apply [[FN]]<τ_0_0>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0>
 // CHECK:   return [[RESULT]] : $s510_______OpaqueSelf<τ_0_0>
 // CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s510_______OpaqueSelfVyxGAA4FooPA2aEP3fooxyFTW'
 struct s510_______OpaqueSelf<Base> : FooP {
@@ -1160,12 +1135,8 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T020opaque_values_silgen9AnyStructVSgACIegir_A2DIegir_TR : $@convention(thin) (@in Optional<AnyStruct>, @guaranteed @callee_guaranteed (@in Optional<AnyStruct>) -> @out AnyStruct) -> @out Optional<AnyStruct> {
 // CHECK: bb0([[ARG0:%.*]] : $Optional<AnyStruct>, [[ARG1:%.*]] : $@callee_guaranteed (@in Optional<AnyStruct>) -> @out AnyStruct):
-// CHECK:   [[COPY_FUNC:%.*]] = copy_value [[ARG1]]
-// CHECK:   [[BORROW_FUNC:%.*]] = begin_borrow [[COPY_FUNC]]
-// CHECK:   [[APPLYARG:%.*]] = apply [[BORROW_FUNC]]([[ARG0]]) : $@callee_guaranteed (@in Optional<AnyStruct>) -> @out AnyStruct
+// CHECK:   [[APPLYARG:%.*]] = apply [[ARG1]]([[ARG0]]) : $@callee_guaranteed (@in Optional<AnyStruct>) -> @out AnyStruct
 // CHECK:   [[RETVAL:%.*]] = enum $Optional<AnyStruct>, #Optional.some!enumelt.1, [[APPLYARG]] : $AnyStruct
-// CHECK:   end_borrow [[BORROW_FUNC]]
-// CHECK:   destroy_value [[COPY_FUNC]]
 // CHECK:   return [[RETVAL]] : $Optional<AnyStruct>
 // CHECK-LABEL: } // end sil function '_T020opaque_values_silgen9AnyStructVSgACIegir_A2DIegir_TR'
 
@@ -1173,15 +1144,11 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ieg_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Any {
 // CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> ()):
-// CHECK:   [[COPY_FUNC:%.*]] = copy_value [[ARG]]
 // CHECK:   [[ASTACK:%.*]] = alloc_stack $Any
 // CHECK:   [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $()
-// CHECK:   [[BORROW_FUNC:%.*]] = begin_borrow [[COPY_FUNC]]
-// CHECK:   [[APPLYARG:%.*]] = apply [[BORROW_FUNC]]() : $@callee_guaranteed () -> ()
+// CHECK:   [[APPLYARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> ()
 // CHECK:   [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*()
 // CHECK:   [[RETVAL:%.*]] = init_existential_value [[LOAD_EXIST]] : $(), $(), $Any
-// CHECK:   end_borrow [[BORROW_FUNC]]
-// CHECK:   destroy_value [[COPY_FUNC]]
 // CHECK:   return [[RETVAL]] : $Any
 // CHECK-LABEL: } // end sil function '_T0Ieg_ypIegr_TR'
 
@@ -1189,34 +1156,28 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0S2iIegdd_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Any {
 // CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> (Int, Int)):
-// CHECK:   [[COPY_FUNC:%.*]] = copy_value [[ARG]]
 // CHECK:   [[ASTACK:%.*]] = alloc_stack $Any
 // CHECK:   [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $(Int, Int)
 // CHECK:   [[TADDR0:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 0
 // CHECK:   [[TADDR1:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 1
-// CHECK:   [[BORROW_FUNC:%.*]] = begin_borrow [[COPY_FUNC]]
-// CHECK:   [[APPLYARG:%.*]] = apply [[BORROW_FUNC]]() : $@callee_guaranteed () -> (Int, Int)
+// CHECK:   [[APPLYARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> (Int, Int)
 // CHECK:   [[TEXTRACT0:%.*]] = tuple_extract [[APPLYARG]] : $(Int, Int), 0
 // CHECK:   [[TEXTRACT1:%.*]] = tuple_extract [[APPLYARG]] : $(Int, Int), 1
 // CHECK:   store [[TEXTRACT0]] to [trivial] [[TADDR0]] : $*Int
 // CHECK:   store [[TEXTRACT1]] to [trivial] [[TADDR1]] : $*Int
 // CHECK:   [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*(Int, Int)
 // CHECK:   [[RETVAL:%.*]] = init_existential_value [[LOAD_EXIST]] : $(Int, Int), $(Int, Int), $Any
-// CHECK:   end_borrow [[BORROW_FUNC]]
 // CHECK:   dealloc_stack [[ASTACK]] : $*Any
-// CHECK:   destroy_value [[COPY_FUNC]]
 // CHECK:   return [[RETVAL]] : $Any
 // CHECK-LABEL: } // end sil function '_T0S2iIegdd_ypIegr_TR'
 
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @{{.*}} : $@convention(thin) (Int, Int, Int, Int, Int, @guaranteed @callee_guaranteed (@in (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)) -> (Int, Int, Int, Int, Int)
 // CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $Int, [[ARG3:%.*]] : $Int, [[ARG4:%.*]] : $Int, [[ARG5:%.*]] : $@callee_guaranteed (@in (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)):
-// CHECK:   [[COPY_FUNC:%.*]] = copy_value [[ARG5]]
 // CHECK:   [[TUPLE_TO_APPLY0:%.*]] = tuple ([[ARG2]] : $Int, [[ARG3]] : $Int)
 // CHECK:   [[TUPLE_TO_APPLY1:%.*]] = tuple ([[ARG1]] : $Int, [[TUPLE_TO_APPLY0]] : $(Int, Int))
 // CHECK:   [[TUPLE_TO_APPLY2:%.*]] = tuple ([[ARG0]] : $Int, [[TUPLE_TO_APPLY1]] : $(Int, (Int, Int)), [[ARG4]] : $Int)
-// CHECK:   [[BORROW_FUNC:%.*]] = begin_borrow [[COPY_FUNC]]
-// CHECK:   [[TUPLE_APPLY:%.*]] = apply [[BORROW_FUNC]]([[TUPLE_TO_APPLY2]]) : $@callee_guaranteed (@in (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)
+// CHECK:   [[TUPLE_APPLY:%.*]] = apply [[ARG5]]([[TUPLE_TO_APPLY2]]) : $@callee_guaranteed (@in (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)
 // CHECK:   [[RET_VAL0:%.*]] = tuple_extract [[TUPLE_APPLY]] : $(Int, (Int, (Int, Int)), Int), 0
 // CHECK:   [[TUPLE_EXTRACT1:%.*]] = tuple_extract [[TUPLE_APPLY]] : $(Int, (Int, (Int, Int)), Int), 1
 // CHECK:   [[RET_VAL1:%.*]] = tuple_extract [[TUPLE_EXTRACT1]] : $(Int, (Int, Int)), 0
@@ -1230,10 +1191,8 @@
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @{{.*}} : $@convention(thin) <T> (Int, @in T, @guaranteed @callee_guaranteed (@in (Int, T)) -> @out (Int, T)) -> (Int, @out T) {
 // CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $T, [[ARG2:%.*]] : $@callee_guaranteed (@in (Int, T)) -> @out (Int, T)):
-// CHECK:   [[COPY_FUNC:%.*]] = copy_value [[ARG2]]
 // CHECK:   [[TUPLE_TO_APPLY:%.*]] = tuple ([[ARG0]] : $Int, [[ARG1]] : $T)
-// CHECK:   [[BORROW_FUNC:%.*]] = begin_borrow [[COPY_FUNC]]
-// CHECK:   [[TUPLE_APPLY:%.*]] = apply [[BORROW_FUNC]]([[TUPLE_TO_APPLY]]) : $@callee_guaranteed (@in (Int, T)) -> @out (Int, T)
+// CHECK:   [[TUPLE_APPLY:%.*]] = apply [[ARG2]]([[TUPLE_TO_APPLY]]) : $@callee_guaranteed (@in (Int, T)) -> @out (Int, T)
 // CHECK:   [[TUPLE_BORROW:%.*]] = begin_borrow [[TUPLE_APPLY]] : $(Int, T)
 // CHECK:   [[RET_VAL0:%.*]] = tuple_extract [[TUPLE_BORROW]] : $(Int, T), 0
 // CHECK:   [[TUPLE_EXTRACT:%.*]] = tuple_extract [[TUPLE_BORROW]] : $(Int, T), 1
@@ -1290,9 +1249,7 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xSgIegr_20opaque_values_silgen8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable> {
 // CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> @out Optional<τ_0_0>):
-// CHECK:   [[COPY:%.*]] = copy_value [[ARG]]
-// CHECK:   [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:   [[APPLY_ARG:%.*]] = apply [[BORROW]]() : $@callee_guaranteed () -> @out Optional<τ_0_0>
+// CHECK:   [[APPLY_ARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> @out Optional<τ_0_0>
 // CHECK:   switch_enum [[APPLY_ARG]] : $Optional<τ_0_0>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
 // CHECK: bb1:
 // CHECK:   [[ONONE:%.*]] = enum $Optional<Clonable>, #Optional.none!enumelt
@@ -1302,7 +1259,6 @@
 // CHECK:   [[OSOME:%.*]] = enum $Optional<Clonable>, #Optional.some!enumelt.1, [[INIT_OPAQUE]] : $Clonable
 // CHECK:   br bb3([[OSOME]] : $Optional<Clonable>)
 // CHECK: bb3([[RETVAL:%.*]] : $Optional<Clonable>):
-// CHECK:   destroy_value [[COPY]]
 // CHECK:   return [[RETVAL]] : $Optional<Clonable>
 // CHECK-LABEL: } // end sil function '_T0xSgIegr_20opaque_values_silgen8Clonable_pSgIegr_AbCRzlTR'
 
@@ -1310,7 +1266,6 @@
 // ---
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0ypIegi_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in Any) -> ()) -> () {
 // CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $@callee_guaranteed (@in Any) -> ()):
-// CHECK:   [[COPY:%.*]] = copy_value [[ARG2]]
 // CHECK:   [[ASTACK:%.*]] = alloc_stack $Any
 // CHECK:   [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $(Int, Int)
 // CHECK:   [[TADDR0:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 0
@@ -1319,9 +1274,7 @@
 // CHECK:   store [[ARG1]] to [trivial] [[TADDR1]] : $*Int
 // CHECK:   [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*(Int, Int)
 // CHECK:   [[INIT_OPAQUE:%.*]] = init_existential_value [[LOAD_EXIST]] : $(Int, Int), $(Int, Int), $Any
-// CHECK:   [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:   [[APPLYARG:%.*]] = apply [[BORROW]]([[INIT_OPAQUE]]) : $@callee_guaranteed (@in Any) -> ()
+// CHECK:   [[APPLYARG:%.*]] = apply [[ARG2]]([[INIT_OPAQUE]]) : $@callee_guaranteed (@in Any) -> ()
 // CHECK:   dealloc_stack [[ASTACK]] : $*Any
-// CHECK:   destroy_value [[COPY]]
 // CHECK:   return %{{.*}} : $()
 // CHECK-LABEL: } // end sil function '_T0ypIegi_S2iIegyy_TR'
diff --git a/test/SILGen/partial_apply_protocol.swift b/test/SILGen/partial_apply_protocol.swift
index d72ae47..2792fda 100644
--- a/test/SILGen/partial_apply_protocol.swift
+++ b/test/SILGen/partial_apply_protocol.swift
@@ -42,26 +42,20 @@
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
 // CHECK:       bb0(%0 : @trivial $*Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_0_0):
-// CHECK-NEXT:    [[COPY:%.*]] = copy_value %1
 // CHECK-NEXT:    [[INNER_RESULT:%.*]] = alloc_stack $τ_0_0
-// CHECK-NEXT:    [[B:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[B]]([[INNER_RESULT]])
+// CHECK-NEXT:    apply %1([[INNER_RESULT]])
 // CHECK-NEXT:    [[OUTER_RESULT:%.*]] = init_existential_addr %0
 // CHECK-NEXT:    copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
 // CHECK-NEXT:    [[EMPTY:%.*]] = tuple ()
-// CHECK-NEXT:    end_borrow [[B]]
 // CHECK-NEXT:    dealloc_stack [[INNER_RESULT]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return [[EMPTY]]
 
 // FIXME: This is horribly inefficient, too much alloc_stack / copy_addr!
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xSgIegr_22partial_apply_protocol8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
 // CHECK:       bb0(%0 : @trivial $*Optional<Clonable>, %1 : @guaranteed $@callee_guaranteed () -> @out Optional<τ_0_0>):
-// CHECK-NEXT:    [[COPY:%.*]] = copy_value %1
 // CHECK-NEXT:    [[INNER_RESULT:%.*]] = alloc_stack $Optional<τ_0_0>
-// CHECK-NEXT:    [[B:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:    apply [[B]]([[INNER_RESULT]])
+// CHECK-NEXT:    apply %1([[INNER_RESULT]])
 // CHECK-NEXT:    [[OUTER_RESULT:%.*]] = alloc_stack $Optional<Clonable>
 // CHECK-NEXT:    switch_enum_addr [[INNER_RESULT]] : $*Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]],
 // CHECK:       [[SOME_BB]]:
@@ -81,30 +75,20 @@
 // CHECK-NEXT:    copy_addr [take] [[OUTER_RESULT]] to [initialization] %0
 // CHECK-NEXT:    [[EMPTY:%.*]] = tuple ()
 // CHECK-NEXT:    dealloc_stack [[OUTER_RESULT]]
-// CHECK-NEXT:    end_borrow [[B]]
 // CHECK-NEXT:    dealloc_stack [[INNER_RESULT]]
-// CHECK-NEXT:    destroy_value [[COPY]]
 // CHECK-NEXT:    return [[EMPTY]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xXMTIegd_22partial_apply_protocol8Clonable_pXmTIegd_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
 // CHECK:       bb0(%0 : @guaranteed $@callee_guaranteed () -> @thick τ_0_0.Type):
-// CHECK-NEXT:    [[C:%.*]] = copy_value %0
-// CHECK-NEXT:    [[B:%.*]] = begin_borrow [[C]]
-// CHECK-NEXT:    [[INNER_RESULT:%.*]] = apply [[B]]()
+// CHECK-NEXT:    [[INNER_RESULT:%.*]] = apply %0()
 // CHECK-NEXT:    [[OUTER_RESULT:%.*]] = init_existential_metatype [[INNER_RESULT]]
-// CHECK-NEXT:    end_borrow [[B]]
-// CHECK-NEXT:    destroy_value [[C]]
 // CHECK-NEXT:    return [[OUTER_RESULT]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xIegr_Iego_22partial_apply_protocol8Clonable_pIegr_Iego_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @owned @callee_guaranteed () -> @out τ_0_0) -> @owned @callee_guaranteed () -> @out Clonable
 // CHECK:       bb0(%0 : @guaranteed $@callee_guaranteed () -> @owned @callee_guaranteed () -> @out τ_0_0):
-// CHECK-NEXT:    [[C:%.*]] = copy_value %0
-// CHECK-NEXT:    [[B:%.*]] = begin_borrow [[C]]
-// CHECK-NEXT:    [[INNER_RESULT:%.*]] = apply [[B]]()
+// CHECK-NEXT:    [[INNER_RESULT:%.*]] = apply %0()
 // CHECK:         [[THUNK_FN:%.*]] = function_ref @_T0xIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR
 // CHECK-NEXT:    [[OUTER_RESULT:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0>([[INNER_RESULT]])
-// CHECK-NEXT:    end_borrow [[B]]
-// CHECK-NEXT:    destroy_value [[C]]
 // CHECK-NEXT:    return [[OUTER_RESULT]]
 
 //===----------------------------------------------------------------------===//
@@ -148,39 +132,27 @@
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xqd__Iegir_x22partial_apply_protocol8Clonable_pIegir_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @out τ_1_0) -> @out Clonable
 // CHECK:         bb0(%0 : @trivial $*Clonable, %1 : @trivial $*τ_0_0, %2 : @guaranteed $@callee_guaranteed (@in τ_0_0) -> @out τ_1_0):
-// CHECK-NEXT:      [[COPY:%.*]] = copy_value %2
 // CHECK-NEXT:      [[INNER_RESULT:%.*]] = alloc_stack $τ_1_0
-// CHECK-NEXT:      [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:      apply [[BORROW]]([[INNER_RESULT]], %1)
+// CHECK-NEXT:      apply %2([[INNER_RESULT]], %1)
 // CHECK-NEXT:      [[OUTER_RESULT:%.*]] = init_existential_addr %0
 // CHECK-NEXT:      copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
 // CHECK-NEXT:      [[EMPTY:%.*]] = tuple ()
-// CHECK-NEXT:      end_borrow [[BORROW]]
 // CHECK-NEXT:      dealloc_stack [[INNER_RESULT]]
-// CHECK-NEXT:      destroy_value [[COPY]]
 // CHECK-NEXT:      return [[EMPTY]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0xqd__Iegr_Iegio_x22partial_apply_protocol8Clonable_pIegr_Iegio_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0) -> @owned @callee_guaranteed () -> @out Clonable
 // CHECK:         bb0(%0 : @trivial $*τ_0_0, %1 : @guaranteed $@callee_guaranteed (@in τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0):
-// CHECK-NEXT:      [[COPY:%.*]] = copy_value %1
-// CHECK-NEXT:      [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:      [[RES:%.*]] = apply [[BORROW]](%0)
+// CHECK-NEXT:      [[RES:%.*]] = apply %1(%0)
 // CHECK:           [[THUNK_FN:%.*]] = function_ref @_T0qd__Iegr_22partial_apply_protocol8Clonable_pIegr_AaBRd__r__lTR
 // CHECK-NEXT:      [[RESULT:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0, τ_1_0>([[RES]])
-// CHECK-NEXT:      end_borrow [[BORROW]]
-// CHECK-NEXT:      destroy_value [[COPY]]
 // CHECK-NEXT:      return [[RESULT]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0qd__Iegr_22partial_apply_protocol8Clonable_pIegr_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_1_0) -> @out Clonable {
 // CHECK:         bb0(%0 : @trivial $*Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_1_0):
-// CHECK-NEXT:      [[COPY:%.*]] = copy_value %1
 // CHECK-NEXT:      [[INNER_RESULT:%.*]] = alloc_stack $τ_1_0
-// CHECK-NEXT:      [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT:      apply [[BORROW]]([[INNER_RESULT]])
+// CHECK-NEXT:      apply %1([[INNER_RESULT]])
 // CHECK-NEXT:      [[OUTER_RESULT:%.*]] = init_existential_addr %0
 // CHECK-NEXT:      copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
 // CHECK-NEXT:      [[EMPTY:%.*]] = tuple ()
-// CHECK-NEXT:      end_borrow [[BORROW]]
 // CHECK-NEXT:      dealloc_stack [[INNER_RESULT:%.*]]
-// CHECK-NEXT:      destroy_value [[COPY]]
 // CHECK-NEXT:      return [[EMPTY]]
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..37d1fbc 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]]
diff --git a/test/SILGen/protocol_resilience.swift b/test/SILGen/protocol_resilience.swift
index 658150d..8ece9cc 100644
--- a/test/SILGen/protocol_resilience.swift
+++ b/test/SILGen/protocol_resilience.swift
@@ -221,6 +221,18 @@
   }
 }
 
+// CHECK-LABEL: sil private [transparent] [thunk] @_T019protocol_resilience21ReabstractSelfRefinedP8callbackxxcvg : $@convention(witness_method: ReabstractSelfRefined) <τ_0_0 where τ_0_0 : ReabstractSelfRefined> (@guaranteed τ_0_0) -> @owned @callee_guaranteed (@owned τ_0_0) -> @owned τ_0_0
+// CHECK: [[SELF_BOX:%.*]] = alloc_stack $τ_0_0
+// CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value %0 : $τ_0_0
+// CHECK-NEXT: store [[SELF_COPY]] to [init] [[SELF_BOX]] : $*τ_0_0
+// CHECK: [[WITNESS:%.*]] = function_ref @_T019protocol_resilience18ReabstractSelfBasePAAE8callbackxxcvg
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS]]<τ_0_0>([[SELF_BOX]])
+// CHECK: [[THUNK_FN:%.*]] = function_ref @_T0xxIegir_xxIegxo_19protocol_resilience21ReabstractSelfRefinedRzlTR
+// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0>([[RESULT]])
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
+// CHECK-NEXT: return [[THUNK]]
+
 final class X : ReabstractSelfRefined {}
 
 func inoutFunc(_ x: inout Int) {}
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 17af5ad..171acba 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -256,15 +256,10 @@
 // ClassWithGetter.
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09protocols15ClassWithGetterCAA08PropertycD0A2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed ClassWithGetter) -> Int {
 // CHECK: bb0([[C:%.*]] : @trivial $*ClassWithGetter):
-// CHECK-NEXT: [[CCOPY:%.*]] = alloc_stack $ClassWithGetter
-// CHECK-NEXT: copy_addr [[C]] to [initialization] [[CCOPY]]
-// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [take] [[CCOPY]]
-// CHECK-NEXT: [[BORROWED_CCOPY_LOADED:%.*]] = begin_borrow [[CCOPY_LOADED]]
-// CHECK-NEXT: [[FUN:%.*]] = class_method [[BORROWED_CCOPY_LOADED]] : $ClassWithGetter, #ClassWithGetter.a!getter.1 : (ClassWithGetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetter) -> Int
-// CHECK-NEXT: apply [[FUN]]([[BORROWED_CCOPY_LOADED]])
-// CHECK-NEXT: end_borrow [[BORROWED_CCOPY_LOADED]] from [[CCOPY_LOADED]]
-// CHECK-NEXT: destroy_value [[CCOPY_LOADED]]
-// CHECK-NEXT: dealloc_stack [[CCOPY]]
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow %0
+// CHECK-NEXT: [[FUN:%.*]] = class_method [[CCOPY_LOADED]] : $ClassWithGetter, #ClassWithGetter.a!getter.1 : (ClassWithGetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetter) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
 // CHECK-NEXT: return
 
 class ClassWithGetterSetter : PropertyWithGetterSetter, PropertyWithGetter {
@@ -284,15 +279,10 @@
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09protocols21ClassWithGetterSetterCAA08PropertycdE0A2aDP1bSivgTW : $@convention(witness_method: PropertyWithGetterSetter) (@in_guaranteed ClassWithGetterSetter) -> Int {
 // CHECK: bb0([[C:%.*]] : @trivial $*ClassWithGetterSetter):
-// CHECK-NEXT: [[CCOPY:%.*]] = alloc_stack $ClassWithGetterSetter
-// CHECK-NEXT: copy_addr [[C]] to [initialization] [[CCOPY]]
-// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [take] [[CCOPY]]
-// CHECK-NEXT: [[BORROWED_CCOPY_LOADED:%.*]] = begin_borrow [[CCOPY_LOADED]]
-// CHECK-NEXT: [[FUN:%.*]] = class_method [[BORROWED_CCOPY_LOADED]] : $ClassWithGetterSetter, #ClassWithGetterSetter.b!getter.1 : (ClassWithGetterSetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetterSetter) -> Int
-// CHECK-NEXT: apply [[FUN]]([[BORROWED_CCOPY_LOADED]])
-// CHECK-NEXT: end_borrow [[BORROWED_CCOPY_LOADED]] from [[CCOPY_LOADED]]
-// CHECK-NEXT: destroy_value [[CCOPY_LOADED]]
-// CHECK-NEXT: dealloc_stack [[CCOPY]]
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow %0
+// CHECK-NEXT: [[FUN:%.*]] = class_method [[CCOPY_LOADED]] : $ClassWithGetterSetter, #ClassWithGetterSetter.b!getter.1 : (ClassWithGetterSetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetterSetter) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
 // CHECK-NEXT: return
 
 // Stored variables fulfilling property requirements
@@ -340,13 +330,10 @@
 //
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09protocols24StructWithStoredPropertyVAA0eC6GetterA2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed StructWithStoredProperty) -> Int {
 // CHECK: bb0([[C:%.*]] : @trivial $*StructWithStoredProperty):
-// CHECK-NEXT: [[CCOPY:%.*]] = alloc_stack $StructWithStoredProperty
-// CHECK-NEXT: copy_addr [[C]] to [initialization] [[CCOPY]]
-// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [trivial] [[CCOPY]]
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [trivial] [[C]]
 // CHECK-NEXT: function_ref
 // CHECK-NEXT: [[FUN:%.*]] = function_ref @_T09protocols24StructWithStoredPropertyV1aSivg : $@convention(method) (StructWithStoredProperty) -> Int
 // CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
-// CHECK-NEXT: dealloc_stack [[CCOPY]]
 // CHECK-NEXT: return
 
 class C {}
@@ -370,16 +357,11 @@
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09protocols29StructWithStoredClassPropertyVAA0fC6GetterA2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed StructWithStoredClassProperty) -> Int {
 // CHECK: bb0([[C:%.*]] : @trivial $*StructWithStoredClassProperty):
-// CHECK-NEXT: [[CCOPY:%.*]] = alloc_stack $StructWithStoredClassProperty
-// CHECK-NEXT: copy_addr [[C]] to [initialization] [[CCOPY]]
-// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [take] [[CCOPY]]
-// CHECK-NEXT: [[BORROWED_CCOPY_LOADED:%.*]] = begin_borrow [[CCOPY_LOADED]]
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow [[C]]
 // CHECK-NEXT: function_ref
 // CHECK-NEXT: [[FUN:%.*]] = function_ref @_T09protocols29StructWithStoredClassPropertyV1aSivg : $@convention(method) (@guaranteed StructWithStoredClassProperty) -> Int
-// CHECK-NEXT: apply [[FUN]]([[BORROWED_CCOPY_LOADED]])
-// CHECK-NEXT: end_borrow [[BORROWED_CCOPY_LOADED]] from [[CCOPY_LOADED]]
-// CHECK-NEXT: destroy_value [[CCOPY_LOADED]]
-// CHECK-NEXT: dealloc_stack [[CCOPY]]
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
 // CHECK-NEXT: return
 
 // rdar://22676810
diff --git a/test/SILGen/reabstract-tuple.swift b/test/SILGen/reabstract-tuple.swift
index 56cfce3..ef9287d 100644
--- a/test/SILGen/reabstract-tuple.swift
+++ b/test/SILGen/reabstract-tuple.swift
@@ -16,13 +16,9 @@
 // CHECK:   [[CLOSURE:%.*]] = function_ref @_T04main7testBoxyyFyycfU_ : $@convention(thin) () -> ()
 // CHECK:   [[THICK:%.*]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
 // CHECK:   [[TUPLEA:%.*]] = tuple (%{{.*}} : $Int, [[THICK]] : $@callee_guaranteed () -> ())
-// CHECK:   [[BORROWA:%.*]] = begin_borrow [[TUPLEA]] : $(Int, @callee_guaranteed () -> ())
-// CHECK:   [[ELTA_0:%.*]] = tuple_extract [[BORROWA]] : $(Int, @callee_guaranteed () -> ()), 0
-// CHECK:   [[ELTA_1:%.*]] = tuple_extract [[BORROWA]] : $(Int, @callee_guaranteed () -> ()), 1
-// CHECK:   [[COPYA_1:%.*]] = copy_value [[ELTA_1]] : $@callee_guaranteed () -> () 
-// CHECK:   end_borrow [[BORROWA]] from %{{.*}} : $(Int, @callee_guaranteed () -> ()), $(Int, @callee_guaranteed () -> ())
+// CHECK:   ([[ELTA_0:%.*]], [[ELTA_1:%.*]]) = destructure_tuple [[TUPLEA]] : $(Int, @callee_guaranteed () -> ())
 // CHECK:   [[THUNK1:%.*]] = function_ref @_T0Ieg_ytytIegir_TR : $@convention(thin) (@in (), @guaranteed @callee_guaranteed () -> ()) -> @out ()
-// CHECK:   [[PA:%.*]] = partial_apply [callee_guaranteed] [[THUNK1]]([[COPYA_1]]) : $@convention(thin) (@in (), @guaranteed @callee_guaranteed () -> ()) -> @out ()
+// CHECK:   [[PA:%.*]] = partial_apply [callee_guaranteed] [[THUNK1]]([[ELTA_1]]) : $@convention(thin) (@in (), @guaranteed @callee_guaranteed () -> ()) -> @out ()
 // CHECK:   [[TUPLEB:%.*]] = tuple ([[ELTA_0]] : $Int, [[PA]] : $@callee_guaranteed (@in ()) -> @out ())
 // CHECK:   [[BORROWB:%.*]] = begin_borrow [[TUPLEB]] : $(Int, @callee_guaranteed (@in ()) -> @out ())
 // CHECK:   [[TUPLEB_0:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_guaranteed (@in ()) -> @out ()), 0
@@ -33,7 +29,6 @@
 // CHECK:   [[CALL:%.*]] = apply [[INIT_F]]<(Int, () -> ())>(%{{.*}}, %{{.*}}) : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0>
 // CHECK:   end_borrow [[BORROWB]] from %{{.*}} : $(Int, @callee_guaranteed (@in ()) -> @out ()), $(Int, @callee_guaranteed (@in ()) -> @out ())
 // CHECK:   destroy_value [[TUPLEB]] : $(Int, @callee_guaranteed (@in ()) -> @out ())
-// CHECK:   destroy_value [[TUPLEA]] : $(Int, @callee_guaranteed () -> ())
 // CHECK:   [[BORROW_CALL:%.*]] = begin_borrow [[CALL]] : $Box<(Int, () -> ())> 
 // CHECK:   [[REF:%.*]] = ref_element_addr [[BORROW_CALL]] : $Box<(Int, () -> ())>, #Box.value
 // CHECK:   [[READ:%.*]] = begin_access [read] [dynamic] [[REF]] : $*(Int, @callee_guaranteed (@in ()) -> @out ())
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index 90ae959..3016671 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -23,14 +23,10 @@
 // CHECK-NEXT: return
 
 // CHECK:    sil shared [transparent] [serializable] [reabstraction_thunk] [[THUNK]] : $@convention(thin) (@in Int, @guaranteed @noescape @callee_guaranteed (Int) -> Optional<Int>) -> @out Optional<Int> {
-// CHECK:      [[COPY:%.*]] = copy_value %2
 // CHECK:      [[T0:%.*]] = load [trivial] %1 : $*Int
-// CHECK:      [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK-NEXT: [[T1:%.*]] = apply [[BORROW]]([[T0]])
+// CHECK-NEXT: [[T1:%.*]] = apply %2([[T0]])
 // CHECK-NEXT: store [[T1]] to [trivial] %0
 // CHECK-NEXT: tuple ()
-// CHECK-NEXT: end_borrow [[BORROW]]
-// CHECK-NEXT: destroy_value [[COPY]]
 // CHECK-NEXT: return
 
 // CHECK-LABEL: sil hidden @_T010reabstract10testThrowsyypF
diff --git a/test/SILGen/shared.swift b/test/SILGen/shared.swift
index 363a60b..56df23f 100644
--- a/test/SILGen/shared.swift
+++ b/test/SILGen/shared.swift
@@ -86,10 +86,7 @@
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[FUNC:%[0-9]+]] : @guaranteed $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()):
   // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
-  // CHECK: [[COPY_FUNC:%.*]] = copy_value [[FUNC]]
-	// CHECK: [[BORROW:%.*]] = begin_borrow [[COPY_FUNC]]
-  // CHECK: {{%.*}} = apply [[BORROW]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
-  // CHECK: destroy_value [[COPY_FUNC]]
+  // CHECK: {{%.*}} = apply [[FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: } // end sil function '_T0Si6shared14ValueAggregateVAA03RefC0CIgyxx_SiAcEIgygg_TR'
   
   return shared_to_owned_conversion { (trivial : Int, val : ValueAggregate, ref : RefAggregate) in }
@@ -113,15 +110,11 @@
 
   // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Si6shared14ValueAggregateVAA03RefC0CIgygg_SiAcEIgyxx_TR : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed @noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[FUNC:%[0-9]+]] : @guaranteed $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()):
-  // CHECK: [[COPY:%.*]] = copy_value [[FUNC]]
   // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
-  // CHECK: [[BORROWED_FUNC:%.*]] = begin_borrow [[COPY]]
-  // CHECK: {{%.*}} = apply [[BORROWED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
-  // CHECK: end_borrow [[BORROWED_FUNC]]
+  // CHECK: {{%.*}} = apply [[FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
   // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
-  // CHECK: destroy_value [[COPY]]
   // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
   // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
   // CHECK: } // end sil function '_T0Si6shared14ValueAggregateVAA03RefC0CIgygg_SiAcEIgyxx_TR'
diff --git a/test/SILGen/vtable_thunks.swift b/test/SILGen/vtable_thunks.swift
index 4b19d47..b71fba5 100644
--- a/test/SILGen/vtable_thunks.swift
+++ b/test/SILGen/vtable_thunks.swift
@@ -228,9 +228,7 @@
 // CHECK:         return [[OUTER]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T013vtable_thunks1SVIegd_ACSgIegd_TR
-// CHECK:         [[COPY:%.*]] = copy_value %0
-// CHECK:         [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:         [[INNER:%.*]] = apply [[BORROW]]()
+// CHECK:         [[INNER:%.*]] = apply %0()
 // CHECK:         [[OUTER:%.*]] = enum $Optional<S>, #Optional.some!enumelt.1, [[INNER]] : $S
 // CHECK:         return [[OUTER]] : $Optional<S>
 
@@ -242,12 +240,11 @@
 // CHECK:         return [[OUTER]]
 
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T013vtable_thunks1SVSgAA4NootCIego_Iegyo_AcA3AapCSgIego_Iegyo_TR
-// CHECK:         [[COPY:%.*]] = copy_value %1
 // CHECK:         [[ARG:%.*]] = enum $Optional<S>, #Optional.some!enumelt.1, %0
-// CHECK:         [[BORROW:%.*]] = begin_borrow [[COPY]]
-// CHECK:         [[INNER:%.*]] = apply [[BORROW]]([[ARG]])
+// CHECK:         [[INNER:%.*]] = apply %1([[ARG]])
 // CHECK:         [[OUTER:%.*]] = convert_function [[INNER]] : $@callee_guaranteed () -> @owned Noot to $@callee_guaranteed () -> @owned Optional<Aap>
 // CHECK:         return [[OUTER]]
+
 // CHECK-LABEL: sil_vtable D {
 // CHECK:         #B.iuo!1: {{.*}} : hidden _T013vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV
 // CHECK:         #B.f!1: {{.*}} : _T013vtable_thunks1D{{[A-Z0-9a-z_]*}}F
diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift
index 53858f4..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()
 }
@@ -168,14 +168,12 @@
   // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses15ConformingClassCAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in ConformingClass, @inout ConformingClass) -> @out ConformingClass {
   // CHECK:  bb0([[ARG1:%.*]] : @trivial $*ConformingClass, [[ARG2:%.*]] : @trivial $*ConformingClass, [[ARG3:%.*]] : @trivial $*ConformingClass):
   // -- load and copy_value 'self' from inout witness 'self' parameter
-  // CHECK:    [[ARG3_LOADED:%.*]] = load [copy] [[ARG3]] : $*ConformingClass
   // CHECK:    [[ARG2_LOADED:%.*]] = load [take] [[ARG2]] : $*ConformingClass
+  // CHECK:    [[ARG3_LOADED:%.*]] = load_borrow [[ARG3]] : $*ConformingClass
   // CHECK:    [[FUNC:%.*]] = function_ref @_T09witnesses15ConformingClassC9selfTypes{{[_0-9a-zA-Z]*}}F
-  // CHECK:    [[BORROWED_ARG3_LOADED:%.*]] = begin_borrow [[ARG3_LOADED]]
-  // CHECK:    [[FUNC_RESULT:%.*]] = apply [[FUNC]]([[ARG2_LOADED]], [[BORROWED_ARG3_LOADED]]) : $@convention(method) (@owned ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
+  // CHECK:    [[FUNC_RESULT:%.*]] = apply [[FUNC]]([[ARG2_LOADED]], [[ARG3_LOADED]]) : $@convention(method) (@owned ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
   // CHECK:    store [[FUNC_RESULT]] to [init] [[ARG1]] : $*ConformingClass
-  // CHECK:    end_borrow [[BORROWED_ARG3_LOADED]] from [[ARG3_LOADED]]
-  // CHECK:    destroy_value [[ARG3_LOADED]]
+  // CHECK:    end_borrow [[ARG3_LOADED]] from [[ARG3]]
   // CHECK:  } // end sil function '_T09witnesses15ConformingClassCAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW'
   func loadable(x: Loadable) -> Loadable { return x }
   func addrOnly(x: AddrOnly) -> AddrOnly { return x }
@@ -187,13 +185,9 @@
 extension ConformingClass : ClassBounded { }
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses15ConformingClassCAA0C7BoundedA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ClassBounded) (@owned ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass {
 // CHECK:  bb0([[C0:%.*]] : @owned $ConformingClass, [[C1:%.*]] : @guaranteed $ConformingClass):
-// CHECK-NEXT:    [[C1_COPY:%.*]] = copy_value [[C1]]
 // CHECK-NEXT:    function_ref
 // CHECK-NEXT:    [[FUN:%.*]] = function_ref @_T09witnesses15ConformingClassC9selfTypes{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT:    [[BORROWED_C1_COPY:%.*]] = begin_borrow [[C1_COPY]]
-// CHECK-NEXT:    [[RESULT:%.*]] = apply [[FUN]]([[C0]], [[BORROWED_C1_COPY]]) : $@convention(method) (@owned ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
-// CHECK-NEXT:    end_borrow [[BORROWED_C1_COPY]] from [[C1_COPY]]
-// CHECK-NEXT:    destroy_value [[C1_COPY]]
+// CHECK-NEXT:    [[RESULT:%.*]] = apply [[FUN]]([[C0]], [[C1]]) : $@convention(method) (@owned ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
 // CHECK-NEXT:    return [[RESULT]] : $ConformingClass
 // CHECK-NEXT:  }
 
@@ -464,16 +458,14 @@
 
   // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP5widthSivmTW : {{.*}} {
   // CHECK: bb0({{.*}} : @trivial $Builtin.RawPointer, {{.*}} : @trivial $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : @trivial $*PropertyRequirementWitnessFromBase):
-  // CHECK-NEXT: [[ARG2_LOADED:%[0-9][0-9]*]] = load [copy] [[ARG2]]
+  // CHECK-NEXT: [[ARG2_LOADED:%[0-9][0-9]*]] = load_borrow [[ARG2]]
   // CHECK-NEXT: [[CAST_ARG2_LOADED:%[0-9][0-9]*]] = upcast [[ARG2_LOADED]] : $PropertyRequirementWitnessFromBase to $PropertyRequirementBase
-  // CHECK-NEXT: [[BORROWED_CAST_ARG2_LOADED:%[0-9][0-9]*]] = begin_borrow [[CAST_ARG2_LOADED]] : $PropertyRequirementBase
-  // CHECK-NEXT: [[METH:%.*]] = class_method [[BORROWED_CAST_ARG2_LOADED]] : $PropertyRequirementBase, #PropertyRequirementBase.width!materializeForSet.1
-  // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[BORROWED_CAST_ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+  // CHECK-NEXT: [[METH:%.*]] = class_method [[CAST_ARG2_LOADED]] : $PropertyRequirementBase, #PropertyRequirementBase.width!materializeForSet.1
+  // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[CAST_ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
   // CHECK-NEXT: [[CAR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 0
   // CHECK-NEXT: [[CADR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 1
   // CHECK-NEXT: [[TUPLE:%.*]] = tuple ([[CAR]] : {{.*}}, [[CADR]] : {{.*}})
-  // CHECK-NEXT: end_borrow [[BORROWED_CAST_ARG2_LOADED]] from [[CAST_ARG2_LOADED]]
-  // CHECK-NEXT: destroy_value [[CAST_ARG2_LOADED]]
+  // CHECK-NEXT: end_borrow [[ARG2_LOADED]] from [[ARG2]]
   // CHECK-NEXT: return [[TUPLE]]
 
   // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP6heightSivmZTW : {{.*}} {
@@ -487,15 +479,13 @@
 
   // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP5depthSivmTW
   // CHECK: bb0({{.*}} : @trivial $Builtin.RawPointer, {{.*}} : @trivial $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : @trivial $*PropertyRequirementWitnessFromBase):
-  // CHECK: [[ARG2_LOADED:%[0-9][0-9]*]] = load [copy] [[ARG2]]
+  // CHECK: [[ARG2_LOADED:%[0-9][0-9]*]] = load_borrow [[ARG2]]
   // CHECK: [[METH:%.*]] = class_method [[ARG2_LOADED]] : $PropertyRequirementWitnessFromBase, #PropertyRequirementWitnessFromBase.depth!materializeForSet.1
-  // CHECK-NEXT: [[BORROWED_ARG2_LOADED:%.*]] = begin_borrow [[ARG2_LOADED]]
-  // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[BORROWED_ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementWitnessFromBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+  // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementWitnessFromBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
   // CHECK-NEXT: tuple_extract
   // CHECK-NEXT: tuple_extract
   // CHECK-NEXT: [[RES:%.*]] = tuple
-  // CHECK-NEXT: end_borrow [[BORROWED_ARG2_LOADED]] from [[ARG2_LOADED]]
-  // CHECK-NEXT: destroy_value [[ARG2_LOADED]]
+  // CHECK-NEXT: end_borrow [[ARG2_LOADED]] from [[ARG2]]
   // CHECK-NEXT: return [[RES]]
 }
 
@@ -509,17 +499,12 @@
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T09witnesses16GenericCrashableCyxGAA0C0A2aEP5crashyyFTW : $@convention(witness_method: Crashable) <τ_0_0> (@in_guaranteed GenericCrashable<τ_0_0>) -> ()
 // CHECK:       bb0(%0 : @trivial $*GenericCrashable<τ_0_0>):
-// CHECK-NEXT: [[BOX:%.*]] = alloc_stack $GenericCrashable<τ_0_0>
-// CHECK-NEXT: copy_addr %0 to [initialization] [[BOX]] : $*GenericCrashable<τ_0_0>
-// CHECK-NEXT: [[SELF:%.*]] = load [take] [[BOX]] : $*GenericCrashable<τ_0_0>
+// CHECK-NEXT: [[SELF:%.*]] = load_borrow %0 : $*GenericCrashable<τ_0_0>
 // CHECK-NEXT: [[BASE:%.*]] = upcast [[SELF]] : $GenericCrashable<τ_0_0> to $CrashableBase
-// CHECK-NEXT: [[BORROWED_BASE:%.*]] = begin_borrow [[BASE]]
-// CHECK-NEXT: [[FN:%.*]] = class_method [[BORROWED_BASE]] : $CrashableBase, #CrashableBase.crash!1 : (CrashableBase) -> () -> (), $@convention(method) (@guaranteed CrashableBase) -> ()
-// CHECK-NEXT: apply [[FN]]([[BORROWED_BASE]]) : $@convention(method) (@guaranteed CrashableBase) -> ()
+// CHECK-NEXT: [[FN:%.*]] = class_method [[BASE]] : $CrashableBase, #CrashableBase.crash!1 : (CrashableBase) -> () -> (), $@convention(method) (@guaranteed CrashableBase) -> ()
+// CHECK-NEXT: apply [[FN]]([[BASE]]) : $@convention(method) (@guaranteed CrashableBase) -> ()
 // CHECK-NEXT: [[RESULT:%.*]] = tuple ()
-// CHECK-NEXT: end_borrow [[BORROWED_BASE]] from [[BASE]]
-// CHECK-NEXT: destroy_value [[BASE]] : $CrashableBase
-// CHECK-NEXT: dealloc_stack [[BOX]] : $*GenericCrashable<τ_0_0>
+// CHECK-NEXT: end_borrow [[SELF]] from %0
 // CHECK-NEXT: return [[RESULT]] : $()
 
 class GenericCrashable<T> : CrashableBase, Crashable {}
diff --git a/test/SILGen/witnesses_inheritance.swift b/test/SILGen/witnesses_inheritance.swift
index 7c43bf8..08417ec 100644
--- a/test/SILGen/witnesses_inheritance.swift
+++ b/test/SILGen/witnesses_inheritance.swift
@@ -35,12 +35,12 @@
 // CHECK-NOT: sil private [transparent] [thunk] @_T021witnesses_inheritance1BCAA7FooableA2aDP3foo{{[_0-9a-zA-Z]*}}FTW
 // CHECK-NOT: sil private [transparent] [thunk] @_T021witnesses_inheritance1BCAA7FooableA2aDP9class_foo{{[_0-9a-zA-Z]*}}FZTW
 // CHECK-LABEL: sil private [transparent] [thunk] @_T021witnesses_inheritance1BCAA8BarrableA2aDP3bar{{[_0-9a-zA-Z]*}}FTW
-// CHECK:         [[B:%.*]] = load [take] {{%.*}} : $*B
+// CHECK:         [[B:%.*]] = load_borrow {{%.*}} : $*B
 // CHECK-NEXT:    [[A:%.*]] = upcast [[B]] : $B to $A
-// CHECK-NEXT:    [[BORROWED_A:%.*]] = begin_borrow [[A]]
-// CHECK-NEXT:    [[METH:%.*]] = class_method [[BORROWED_A]] : $A, #A.bar!1
-// CHECK-NEXT:    apply [[METH]]([[BORROWED_A]]) : $@convention(method) (@guaranteed A) -> ()
-// CHECK:         end_borrow [[BORROWED_A]] from [[A]]
+// CHECK-NEXT:    [[METH:%.*]] = class_method [[A]] : $A, #A.bar!1
+// CHECK-NEXT:    apply [[METH]]([[A]]) : $@convention(method) (@guaranteed A) -> ()
+// CHECK:         end_borrow [[B]] from {{.*}}
+
 // CHECK-LABEL: sil private [transparent] [thunk] @_T021witnesses_inheritance1BCAA8BarrableA2aDP9class_bar{{[_0-9a-zA-Z]*}}FZTW
 // CHECK:         upcast {{%.*}} : $@thick B.Type to $@thick A.Type
 
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/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/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_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/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/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/enum_equatable_conditional.swift b/test/Sema/enum_equatable_conditional.swift
new file mode 100644
index 0000000..eab8d00
--- /dev/null
+++ b/test/Sema/enum_equatable_conditional.swift
@@ -0,0 +1,26 @@
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
+
+struct NotEquatable { }
+
+enum WithArrayOfNotEquatables : Equatable { // expected-error{{type 'WithArrayOfNotEquatables' does not conform to protocol 'Equatable'}}
+case only([NotEquatable])
+}
+
+enum WithArrayOfNotEquatables2<T> : Equatable { // expected-error{{type 'WithArrayOfNotEquatables2<T>' does not conform to protocol 'Equatable'}}
+case only([T])
+}
+
+
+// Okay: T is Equatable
+enum WithArrayOfEquatables1<T: Equatable> : Equatable {
+case only([T])
+}
+
+enum WithArrayOfEquatables2<T> {
+case only([T])
+}
+
+// No: T is Equatable here, but cannot synthesize via an extension.
+// expected-error@+1{{type 'WithArrayOfEquatables2<T>' does not conform to protocol 'Equatable'}}
+extension WithArrayOfEquatables2: Equatable where T: Equatable { }
+
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 b/test/SourceKit/DocSupport/doc_clang_module.swift
index 63d95ec..ec01ab5 100644
--- a/test/SourceKit/DocSupport/doc_clang_module.swift
+++ b/test/SourceKit/DocSupport/doc_clang_module.swift
@@ -2,3 +2,6 @@
 // RUN: %sourcekitd-test -req=doc-info -module Foo -- -F %S/../Inputs/libIDE-mock-sdk \
 // RUN:         %mcp_opt %clang-importer-sdk | %sed_clean > %t.response
 // RUN: diff -u %s.response %t.response
+//
+// REQUIRES: rdar35799113
+//
diff --git a/test/SourceKit/InterfaceGen/gen_swift_type.swift b/test/SourceKit/InterfaceGen/gen_swift_type.swift
index 1422d41..a068083 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_type.swift
+++ b/test/SourceKit/InterfaceGen/gen_swift_type.swift
@@ -5,6 +5,8 @@
 // RUN: %sourcekitd-test -req=interface-gen -usr _TtGC14gen_swift_type1DCS_2T1_ %s -- %s | %FileCheck -check-prefix=CHECK5 %s
 // RUN: %sourcekitd-test -req=interface-gen -usr _TtGC14gen_swift_type1DSi_ %s -- %s | %FileCheck -check-prefix=CHECK6 %s
 
+// REQUIRES: rdar35799113
+
 public struct A {
 	public func fa() {}
 }
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/Syntax/Inputs/serialize_multiple_decls.json b/test/Syntax/Inputs/serialize_multiple_decls.json
index 286afe4..08a03b4 100644
--- a/test/Syntax/Inputs/serialize_multiple_decls.json
+++ b/test/Syntax/Inputs/serialize_multiple_decls.json
@@ -1,148 +1,247 @@
-[
-  {
-    "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": "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"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "identifier",
+                            "text": "A"
+                          },
+                          "leadingTrivia": [
+
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "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": "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"
+                        },
+                        {
+                          "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..d33e981 100644
--- a/test/Syntax/Inputs/serialize_struct_decl.json
+++ b/test/Syntax/Inputs/serialize_struct_decl.json
@@ -1,265 +1,404 @@
-[
-  {
-    "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": "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"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "identifier",
+                            "text": "Foo"
+                          },
+                          "leadingTrivia": [
+
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "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 cb0d5e0..308a5f4 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -4,40 +4,83 @@
 // 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 bar(_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>) <CodeBlock>{}</CodeBlock>
+  func bar1(_ a: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>) -> <SimpleTypeIdentifier>Float </SimpleTypeIdentifier><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>
+  func bar2(a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>, b: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>, c:<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
+  func bar3(a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
+  func bar4(_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
   func foo() <CodeBlock>{
-    var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr>
-    var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr><IdentifierExpr>
+    var a = <StringLiteralExpr>/*comment*/"ab\(x)c"</StringLiteralExpr>/*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 = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr><IdentifierExpr>
+    var f = <PrefixOperatorExpr>/*comments*/+<FloatLiteralExpr>0.1</FloatLiteralExpr></PrefixOperatorExpr><IdentifierExpr>/*comments*/
     foo</IdentifierExpr>()
   }</CodeBlock>
 
-  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() <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>
+  func boolAnd() -> <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier><CodeBlock>{ <ReturnStmt>return <SequenceExpr><BooleanLiteralExpr>true </BooleanLiteralExpr><BinaryOperatorExpr>&& </BinaryOperatorExpr><BooleanLiteralExpr>false </BooleanLiteralExpr></SequenceExpr></ReturnStmt>}</CodeBlock>
+  func boolOr() -> <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier><CodeBlock>{ <ReturnStmt>return <SequenceExpr><BooleanLiteralExpr>true </BooleanLiteralExpr><BinaryOperatorExpr>|| </BinaryOperatorExpr><BooleanLiteralExpr>false </BooleanLiteralExpr></SequenceExpr></ReturnStmt>}</CodeBlock>
 
-  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>
+  func foo2() <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>
+
+  func foo3() <CodeBlock>{<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>
 }
+
+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>
+
+struct foo <MemberDeclBlock>{
+  struct foo <MemberDeclBlock>{
+    struct foo <MemberDeclBlock>{
+      func foo() <CodeBlock>{
+      }</CodeBlock>
+    }</MemberDeclBlock>
+  }</MemberDeclBlock>
+  struct foo <MemberDeclBlock>{}</MemberDeclBlock>
+}</MemberDeclBlock>
+
+struct foo <MemberDeclBlock>{<Attribute>
+  @available(*, unavailable)</Attribute>
+  struct foo <MemberDeclBlock>{}</MemberDeclBlock>
+  public class foo {<Attribute>
+    @available(*, unavailable)</Attribute><Attribute>
+    @objc(fooObjc)</Attribute>
+    private static func foo() <CodeBlock>{}</CodeBlock>
+  }
+}</MemberDeclBlock>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index a9d72bb..c5061da 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -10,7 +10,7 @@
   func bar3(a: Int) -> Int { return 1 }
   func bar4(_ a: Int) -> Int { return 1 }
   func foo() {
-    var a = /*comment*/"abc"/*comment*/
+    var a = /*comment*/"ab\(x)c"/*comment*/
     var b = /*comment*/+2/*comment*/
     bar(1)
     bar(+10)
@@ -39,5 +39,48 @@
   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() {
+    _ = 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() {}
   }
 }
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/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/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/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/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/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/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/DoubleWidth.swift b/test/stdlib/DoubleWidth.swift
new file mode 100644
index 0000000..7103e9c
--- /dev/null
+++ b/test/stdlib/DoubleWidth.swift
@@ -0,0 +1,358 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+// FIXME(double-width): <rdar://problem/32726173>
+// REQUIRES: rdar32726173
+
+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/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..28d6b24 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)
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/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index 489261a..24cc312 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -19,63 +19,16 @@
 // REQUIRES: executable_test
 // REQUIRES: objc_interop
 
+// FIXME: rdar://35814988
+// UNSUPPORTED: CPU=armv7
+// 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 +429,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 +468,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 +648,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 +698,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 +748,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/type/protocol_composition.swift b/test/type/protocol_composition.swift
index d6c832f..0d9e2c2 100644
--- a/test/type/protocol_composition.swift
+++ b/test/type/protocol_composition.swift
@@ -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/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/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 7848c72..0d16d95 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.haveUniquePrimaryInput() &&
+           "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.haveInputFilenames()) {
       Invocation.setModuleName("__main__");
       return;
     }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
index 501641f..2b6795c 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.haveInputFilenames()) {
     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..640ce9b 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);
     }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
index 918bbf7..a4018bd 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.haveInputFilenames()) {
     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..1a4c557 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(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/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp
index 397a394..9742b27 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 haveUniqueInputFilename() const { return InputFilenames.size() == 1; }
   const std::string &getFilenameOfFirstInput() const {
     return InputFilenames[0];
   }
@@ -131,7 +131,7 @@
     return 1;
   }
 
-  if (!Invocation.hasUniqueInputFilename()) {
+  if (!Invocation.haveUniqueInputFilename()) {
     Instance.getDiags().diagnose(SourceLoc(),
                                  diag::error_mode_requires_one_input_file);
     return 1;
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index b222dcd..128d14c 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 =
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 2b18f5c..d4a4c7b 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -1917,7 +1917,7 @@
                                      bool AnnotatePrint) {
   CompilerInvocation Invocation(InitInvok);
   Invocation.addInputFilename(SourceFilename);
-  Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
+  Invocation.getFrontendOptions().Inputs.setPrimaryInputToFirstFile();
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   CompilerInstance CI;
   // Display diagnostics to stderr.
@@ -1948,7 +1948,7 @@
                         bool AnnotatePrint) {
   CompilerInvocation Invocation(InitInvok);
   Invocation.addInputFilename(SourceFilename);
-  Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
+  Invocation.getFrontendOptions().Inputs.setPrimaryInputToFirstFile();
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   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..1bb6b73 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"),
@@ -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/Syntax/DeclSyntaxTests.cpp b/unittests/Syntax/DeclSyntaxTests.cpp
index f41f846..5e737c8 100644
--- a/unittests/Syntax/DeclSyntaxTests.cpp
+++ b/unittests/Syntax/DeclSyntaxTests.cpp
@@ -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(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(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,7 +215,8 @@
 
   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,
@@ -251,7 +252,8 @@
 
   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,
@@ -297,7 +299,7 @@
 
   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({}, {});
 
   {
@@ -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/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/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..1b4ac56 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() {
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..8ad68d3
--- /dev/null
+++ b/utils/build_swift/argparse/__init__.py
@@ -0,0 +1,53 @@
+# 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, PathType, RegexType,
+                    SwiftVersionType)
+
+
+__all__ = [
+    'Action',
+    'ArgumentDefaultsHelpFormatter',
+    'ArgumentError',
+    'ArgumentParser',
+    'ArgumentTypeError',
+    'HelpFormatter',
+    'Namespace',
+    'Nargs',
+    'RawDescriptionHelpFormatter',
+    'RawTextHelpFormatter',
+
+    'BoolType',
+    'FileType',
+    'PathType',
+    'RegexType',
+    'ClangVersionType',
+    'SwiftVersionType',
+
+    '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..02fcb61
--- /dev/null
+++ b/utils/build_swift/argparse/actions.py
@@ -0,0 +1,340 @@
+# 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
+        if '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):
+        kwargs['nargs'] = Nargs.SINGLE
+        kwargs['type'] = PathType()
+        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..b01cf9c
--- /dev/null
+++ b/utils/build_swift/argparse/types.py
@@ -0,0 +1,141 @@
+# 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__ = [
+    'BoolType',
+    'PathType',
+    'RegexType',
+    'ClangVersionType',
+    'SwiftVersionType',
+]
+
+
+# -----------------------------------------------------------------------------
+
+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))
+
+
+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):
+        self.assert_exists = assert_exists
+
+    def __call__(self, path):
+        path = os.path.expanduser(path)
+        path = os.path.abspath(path)
+        path = os.path.realpath(path)
+
+        if self.assert_exists:
+            assert os.path.exists(path)
+
+        return path
+
+
+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 value
+
+
+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)
+
+
+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)
+
+
+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)
diff --git a/utils/build_swift/defaults.py b/utils/build_swift/defaults.py
index 50d6523..3e8baa0 100644
--- a/utils/build_swift/defaults.py
+++ b/utils/build_swift/defaults.py
@@ -12,6 +12,9 @@
 
 __all__ = [
     # Command line configuarable
+    'BUILD_VARIANT',
+    'CMAKE_GENERATOR',
+    'COMPILER_VENDOR',
     'SWIFT_USER_VISIBLE_VERSION',
     'CLANG_USER_VISIBLE_VERSION',
     'SWIFT_ANALYZE_CODE_COVERAGE',
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index bcb4072..6bee26c 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -6,7 +6,7 @@
 # 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
@@ -14,10 +14,10 @@
 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 +59,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 +104,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 +224,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 +232,910 @@
         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()
 
+    # Prepare DSL functions
+    option = builder.add_option
+    set_defaults = builder.set_defaults
+    in_group = builder.in_group
+    mutually_exclusive_group = builder.mutually_exclusive_group
+
+    # Prepare DSL actions
+    store = builder.actions.store
+    store_path = builder.actions.store_path
+
+    # -------------------------------------------------------------------------
+    # Top-level options
+
+    parser.add_argument(
+        '-n', '--dry-run',
+        action='store_true',
+        default=False,
+        help='print the commands that would be executed, but do not execute '
+             'them')
+    parser.add_argument(
+        '--no-legacy-impl',
+        action='store_false',
+        dest='legacy_impl',
+        default=True,
+        help='avoid legacy implementation')
+
+    parser.add_argument(
+        '--build-runtime-with-host-compiler',
+        action=arguments.action.enable,
+        help='Use the host compiler, not the self-built one to compile the '
+             'Swift runtime')
+
+    parser.add_argument(
+        '-i', '--ios',
+        action='store_true',
+        help='also build for iOS, but disallow tests that require an iOS '
+             'device')
+    parser.add_argument(
+        '-I', '--ios-all',
+        action='store_true',
+        dest='ios_all',
+        help='also build for iOS, and allow all iOS tests')
+    parser.add_argument(
+        '--skip-ios',
+        action='store_false',
+        dest='ios',
+        help='set to skip everything iOS-related')
+
+    parser.add_argument(
+        '--tvos',
+        action=arguments.action.enable,
+        help='also build for tvOS, but disallow tests that require a tvos '
+             'device')
+    parser.add_argument(
+        '--tvos-all',
+        action=arguments.action.enable,
+        dest='tvos_all',
+        help='also build for tvOS, and allow all tvOS tests')
+    parser.add_argument(
+        '--skip-tvos',
+        action='store_false',
+        dest='tvos',
+        help='set to skip everything tvOS-related')
+
+    parser.add_argument(
+        '--watchos',
+        action=arguments.action.enable,
+        help='also build for watchOS, but disallow tests that require an '
+             'watchOS device')
+    parser.add_argument(
+        '--watchos-all',
+        action=arguments.action.enable,
+        dest='watchos_all',
+        help='also build for Apple watchOS, and allow all Apple watchOS tests')
+    parser.add_argument(
+        '--skip-watchos',
+        action='store_false',
+        dest='watchos',
+        help='set to skip everything watchOS-related')
+
+    parser.add_argument(
+        '--android',
+        action=arguments.action.enable,
+        help='also build for Android')
+
+    parser.add_argument(
+        '--swift-analyze-code-coverage',
+        dest='swift_analyze_code_coverage',
+        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).')
+
+    parser.add_argument(
+        '--build-subdir',
+        metavar='PATH',
+        help='name of the directory under $SWIFT_BUILD_ROOT where the build '
+             'products will be placed')
+    parser.add_argument(
+        '--install-prefix',
+        default=targets.install_prefix(),
+        metavar='PATH',
+        help='The installation prefix. This is where built Swift products '
+             '(like bin, lib, and include) will be installed.')
+    parser.add_argument(
+        '--install-symroot',
+        metavar='PATH',
+        help='the path to install debug symbols into')
+
+    parser.add_argument(
+        '-j', '--jobs',
+        type=int,
+        dest='build_jobs',
+        default=multiprocessing.cpu_count(),
+        help='the number of parallel build jobs to use')
+
+    parser.add_argument(
+        '--darwin-xcrun-toolchain',
+        default=defaults.DARWIN_XCRUN_TOOLCHAIN,
+        help='the name of the toolchain to use on Darwin')
+    parser.add_argument(
+        '--cmake',
+        type=arguments.type.executable,
+        metavar='PATH',
+        help='the path to a CMake executable that will be used to build '
+             'Swift')
+    parser.add_argument(
+        '--show-sdks',
+        action=arguments.action.enable,
+        help='print installed Xcode and SDK versions')
+
+    parser.add_argument(
+        '--extra-swift-args',
+        action='append',
+        dest='extra_swift_args',
+        default=[],
+        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 "\\"')
+
+    parser.add_argument(
+        '--host-cc',
+        type=arguments.type.executable,
+        metavar='PATH',
+        help='the absolute path to CC, the "clang" compiler for the host '
+             'platform. Default is auto detected.')
+    parser.add_argument(
+        '--host-cxx',
+        type=arguments.type.executable,
+        metavar='PATH',
+        help='the absolute path to CXX, the "clang++" compiler for the host '
+             'platform. Default is auto detected.')
+    parser.add_argument(
+        '--host-lipo',
+        type=arguments.type.executable,
+        metavar='PATH',
+        help='the absolute path to lipo. Default is auto detected.')
+    parser.add_argument(
+        '--host-libtool',
+        type=arguments.type.executable,
+        metavar='PATH',
+        help='the absolute path to libtool. Default is auto detected.')
+    parser.add_argument(
+        '--distcc',
+        action=arguments.action.enable,
+        help='use distcc in pump mode')
+    parser.add_argument(
+        '--enable-asan',
+        action=arguments.action.enable,
+        help='enable Address Sanitizer')
+    parser.add_argument(
+        '--enable-ubsan',
+        action=arguments.action.enable,
+        help='enable Undefined Behavior Sanitizer')
+    parser.add_argument(
+        '--enable-tsan',
+        action=arguments.action.enable,
+        help='enable Thread Sanitizer for swift tools')
+    parser.add_argument(
+        '--enable-tsan-runtime',
+        action=arguments.action.enable,
+        help='enable Thread Sanitizer on the swift runtime')
+    parser.add_argument(
+        '--enable-lsan',
+        action=arguments.action.enable,
+        help='enable Leak Sanitizer for swift tools')
+
+    parser.add_argument(
+        '--compiler-vendor',
+        choices=['none', 'apple'],
+        default=defaults.COMPILER_VENDOR,
+        help='Compiler vendor name')
+    parser.add_argument(
+        '--clang-compiler-version',
+        type=arguments.type.clang_compiler_version,
+        metavar='MAJOR.MINOR.PATCH',
+        help='string that indicates a compiler version for Clang')
+    parser.add_argument(
+        '--clang-user-visible-version',
+        type=arguments.type.clang_compiler_version,
+        default=defaults.CLANG_USER_VISIBLE_VERSION,
+        metavar='MAJOR.MINOR.PATCH',
+        help='User-visible version of the embedded Clang and LLVM compilers')
+    parser.add_argument(
+        '--swift-compiler-version',
+        type=arguments.type.swift_compiler_version,
+        metavar='MAJOR.MINOR',
+        help='string that indicates a compiler version for Swift')
+    parser.add_argument(
+        '--swift-user-visible-version',
+        type=arguments.type.swift_compiler_version,
+        default=defaults.SWIFT_USER_VISIBLE_VERSION,
+        metavar='MAJOR.MINOR',
+        help='User-visible version of the embedded Swift compiler')
+
+    parser.add_argument(
+        '--darwin-deployment-version-osx',
+        default=defaults.DARWIN_DEPLOYMENT_VERSION_OSX,
+        metavar='MAJOR.MINOR',
+        help='minimum deployment target version for OS X')
+    parser.add_argument(
+        '--darwin-deployment-version-ios',
+        default=defaults.DARWIN_DEPLOYMENT_VERSION_IOS,
+        metavar='MAJOR.MINOR',
+        help='minimum deployment target version for iOS')
+    parser.add_argument(
+        '--darwin-deployment-version-tvos',
+        default=defaults.DARWIN_DEPLOYMENT_VERSION_TVOS,
+        metavar='MAJOR.MINOR',
+        help='minimum deployment target version for tvOS')
+    parser.add_argument(
+        '--darwin-deployment-version-watchos',
+        default=defaults.DARWIN_DEPLOYMENT_VERSION_WATCHOS,
+        metavar='MAJOR.MINOR',
+        help='minimum deployment target version for watchOS')
+
+    parser.add_argument(
+        '--extra-cmake-options',
+        action=arguments.action.concat,
+        type=arguments.type.shell_split,
+        default=[],
+        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.')
+
+    parser.add_argument(
+        '--build-args',
+        type=arguments.type.shell_split,
+        default=[],
+        help='arguments to the build tool. This would be prepended to the '
+             'default argument that is "-j8" when CMake generator is '
+             '"Ninja".')
+
+    parser.add_argument(
+        '--verbose-build',
+        action=arguments.action.enable,
+        help='print the commands executed during the build')
+
+    parser.add_argument(
+        '--lto',
+        dest='lto_type',
+        nargs='?',
+        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')
+
+    parser.add_argument(
+        '--clang-profile-instr-use',
+        metavar='PATH',
+        help='profile file to use for clang PGO')
+
+    default_max_lto_link_job_counts = host.max_lto_link_job_counts()
+    parser.add_argument(
+        '--llvm-max-parallel-lto-link-jobs',
+        default=default_max_lto_link_job_counts['llvm'],
+        metavar='COUNT',
+        help='the maximum number of parallel link jobs to use when compiling '
+             'llvm')
+
+    parser.add_argument(
+        '--swift-tools-max-parallel-lto-link-jobs',
+        default=default_max_lto_link_job_counts['swift'],
+        metavar='COUNT',
+        help='the maximum number of parallel link jobs to use when compiling '
+             'swift tools.')
+
+    parser.add_argument(
+        '--enable-sil-ownership',
+        action='store_true',
+        help='Enable the SIL ownership model')
+
+    parser.add_argument(
+        '--force-optimized-typechecker',
+        action='store_true',
+        help='Force the type checker to be built with '
+             'optimization')
+
+    parser.add_argument(
+        '--lit-args',
+        default='-sv',
+        metavar='LITARGS',
+        help='lit args to use when testing')
+
+    parser.add_argument(
+        '--coverage-db',
+        metavar='PATH',
+        help='coverage database to use when prioritizing testing')
+
+    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)
+
+    # -------------------------------------------------------------------------
     targets_group = parser.add_argument_group(
-        title="Host and cross-compilation targets")
+        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)
+        '--host-target',
+        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.')
     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=[])
+        '--cross-compile-hosts',
+        action=arguments.action.concat,
+        type=arguments.type.shell_split,
+        default=[],
+        help='A space separated list of targets to cross-compile host Swift '
+             'tools for. Can be used multiple times.')
     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)
+        '--stdlib-deployment-targets',
+        action=arguments.action.concat,
+        type=arguments.type.shell_split,
+        default=None,
+        help='list of targets to compile or cross-compile the Swift standard '
+             'library for. %(default)s by default.')
     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"])
+        '--build-stdlib-deployment-targets',
+        type=arguments.type.shell_split,
+        default=['all'],
+        help='A space-separated list that filters which of the configured '
+             'targets to build the Swift standard library for, or "all".')
 
+    # -------------------------------------------------------------------------
     projects_group = parser.add_argument_group(
-        title="Options to select projects")
+        title='Options to select projects')
     projects_group.add_argument(
-        "-l", "--lldb",
-        help="build LLDB",
-        action="store_true",
-        dest="build_lldb")
+        '-l', '--lldb',
+        action='store_true',
+        dest='build_lldb',
+        help='build LLDB')
     projects_group.add_argument(
-        "-b", "--llbuild",
-        help="build llbuild",
-        action="store_true",
-        dest="build_llbuild")
+        '-b', '--llbuild',
+        action='store_true',
+        dest='build_llbuild',
+        help='build llbuild')
     projects_group.add_argument(
-        "-p", "--swiftpm",
-        help="build swiftpm",
-        action="store_true",
-        dest="build_swiftpm")
+        '-p', '--swiftpm',
+        action='store_true',
+        dest='build_swiftpm',
+        help='build swiftpm')
     projects_group.add_argument(
-        "--xctest",
-        help="build xctest",
+        '--xctest',
         action=arguments.action.enable,
-        dest="build_xctest")
+        dest='build_xctest',
+        help='build xctest')
     projects_group.add_argument(
-        "--foundation",
-        help="build foundation",
+        '--foundation',
         action=arguments.action.enable,
-        dest="build_foundation")
+        dest='build_foundation',
+        help='build foundation')
     projects_group.add_argument(
-        "--libdispatch",
-        help="build libdispatch",
+        '--libdispatch',
         action=arguments.action.enable,
-        dest="build_libdispatch")
+        dest='build_libdispatch',
+        help='build libdispatch')
     projects_group.add_argument(
-        "--libicu",
-        help="build libicu",
+        '--libicu',
         action=arguments.action.enable,
-        dest="build_libicu")
+        dest='build_libicu',
+        help='build libicu')
     projects_group.add_argument(
-        "--playgroundlogger",
-        help="build playgroundlogger",
-        action="store_true",
-        dest="build_playgroundlogger")
+        '--playgroundlogger',
+        action='store_true',
+        dest='build_playgroundlogger',
+        help='build playgroundlogger')
     projects_group.add_argument(
-        "--playgroundsupport",
-        help="build PlaygroundSupport",
-        action="store_true",
-        dest="build_playgroundsupport")
+        '--playgroundsupport',
+        action='store_true',
+        dest='build_playgroundsupport',
+        help='build PlaygroundSupport')
     projects_group.add_argument(
-        "--build-ninja",
-        help="build the Ninja tool",
-        action=arguments.action.enable)
+        '--build-ninja',
+        action=arguments.action.enable,
+        help='build the Ninja tool')
 
+    # -------------------------------------------------------------------------
     extra_actions_group = parser.add_argument_group(
-        title="Extra actions to perform before or in addition to building")
+        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")
+        '-c', '--clean',
+        action='store_true',
+        help='do a clean build')
     extra_actions_group.add_argument(
-        "--export-compile-commands",
-        help="generate compilation databases in addition to building",
-        action=arguments.action.enable)
+        '--export-compile-commands',
+        action=arguments.action.enable,
+        help='generate compilation databases in addition to building')
     extra_actions_group.add_argument(
-        "--symbols-package",
-        metavar="PATH",
-        help="if provided, an archive of the symbols directory will be "
-             "generated at this path")
+        '--symbols-package',
+        metavar='PATH',
+        help='if provided, an archive of the symbols directory will be '
+             'generated at this path')
 
+    # -------------------------------------------------------------------------
     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")
+        '-d', '--debug',
+        action='store_const',
+        const='Debug',
+        dest='build_variant',
+        help='build the Debug variant of everything (LLVM, Clang, Swift host '
+             'tools, target Swift standard libraries, LLDB (if enabled) '
+             '(default)')
     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")
+        '-r', '--release-debuginfo',
+        action='store_const',
+        const='RelWithDebInfo',
+        dest='build_variant',
+        help='build the RelWithDebInfo variant of everything (default is '
+             'Debug)')
     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")
+        '-R', '--release',
+        action='store_const',
+        const='Release',
+        dest='build_variant',
+        help='build the Release variant of everything (default is Debug)')
 
+    # -------------------------------------------------------------------------
     build_variant_override_group = parser.add_argument_group(
-        title="Override build variant for a specific project")
+        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")
+        '--debug-llvm',
+        action='store_const',
+        const='Debug',
+        dest='llvm_build_variant',
+        help='build the Debug variant of LLVM')
     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")
+        '--debug-swift',
+        action='store_const',
+        const='Debug',
+        dest='swift_build_variant',
+        help='build the Debug variant of Swift host tools')
     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")
+        '--debug-swift-stdlib',
+        action='store_const',
+        const='Debug',
+        dest='swift_stdlib_build_variant',
+        help='build the Debug variant of the Swift standard library and SDK '
+             'overlay')
     build_variant_override_group.add_argument(
-        "--debug-lldb",
-        help="build the Debug variant of LLDB",
-        action="store_const",
-        const="Debug",
-        dest="lldb_build_variant")
+        '--debug-lldb',
+        action='store_const',
+        const='Debug',
+        dest='lldb_build_variant',
+        help='build the Debug variant of LLDB')
     build_variant_override_group.add_argument(
-        "--debug-cmark",
-        help="build the Debug variant of CommonMark",
-        action="store_const",
-        const="Debug",
-        dest="cmark_build_variant")
+        '--debug-cmark',
+        action='store_const',
+        const='Debug',
+        dest='cmark_build_variant',
+        help='build the Debug variant of CommonMark')
     build_variant_override_group.add_argument(
-        "--debug-foundation",
-        help="build the Debug variant of Foundation",
-        action="store_const",
-        const="Debug",
-        dest="foundation_build_variant")
+        '--debug-foundation',
+        action='store_const',
+        const='Debug',
+        dest='foundation_build_variant',
+        help='build the Debug variant of Foundation')
     build_variant_override_group.add_argument(
-        "--debug-libdispatch",
-        help="build the Debug variant of libdispatch",
-        action="store_const",
-        const="Debug",
-        dest="libdispatch_build_variant")
+        '--debug-libdispatch',
+        action='store_const',
+        const='Debug',
+        dest='libdispatch_build_variant',
+        help='build the Debug variant of libdispatch')
     build_variant_override_group.add_argument(
-        "--debug-libicu",
-        help="build the Debug variant of libicu",
-        action="store_const",
-        const="Debug",
-        dest="libicu_build_variant")
+        '--debug-libicu',
+        action='store_const',
+        const='Debug',
+        dest='libicu_build_variant',
+        help='build the Debug variant of libicu')
 
-    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")
+    # -------------------------------------------------------------------------
+    # Assertions group
 
-    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")
+    with mutually_exclusive_group():
+        set_defaults(assertions=True)
 
-    # 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")
+        # 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)")
+
+    # -------------------------------------------------------------------------
     run_tests_group = parser.add_argument_group(
-        title="Run tests")
+        title='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",
+        '-t',
+        action='store_const',
         const=True,
-        dest="test")
+        dest='test',
+        help='test Swift after building')
     run_tests_group.add_argument(
-        "--test",
-        help="test Swift after building",
-        action=arguments.action.enable)
+        '--test',
+        action=arguments.action.enable,
+        help='test Swift after building')
     run_tests_group.add_argument(
-        "-T",
-        help="run the validation test suite (implies --test)",
-        action="store_const",
+        '-T',
+        action='store_const',
         const=True,
-        dest="validation_test")
+        dest='validation_test',
+        help='run the validation test suite (implies --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)
-
-    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",
+        '--validation-test',
         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")
-
-    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)")
-
-    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)")
-
-    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)")
-
-    run_build_group.add_argument(
-        "--skip-build-android",
-        dest='build_android',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for Android")
-
-    run_build_group.add_argument(
-        "--skip-build-benchmarks",
-        dest='build_benchmarks',
-        action=arguments.action.disable,
-        help="skip building Swift Benchmark Suite")
-
-    run_build_group.add_argument(
-        "--build-external-benchmarks",
-        dest='build_external_benchmarks',
-        action=arguments.action.enable,
-        help="skip building Swift Benchmark Suite")
-
-    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)")
-
-    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")
-
-    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")
-
-    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")
-
-    parser.add_argument(
-        "--android",
-        help="also build for Android",
-        action=arguments.action.enable)
-
-    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")
-
-    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")
-
-    parser.add_argument(
-        "-j", "--jobs",
-        help="the number of parallel build jobs to use",
-        type=int,
-        dest="build_jobs",
-        default=multiprocessing.cpu_count())
-
-    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)
-
-    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=[])
-
-    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")
-
-    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")
-
-    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)
-
-    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")
-
-    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)
-
-    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.",
+        help='run the validation test suite (implies --test)')
+    run_tests_group.add_argument(
+        '--test-paths',
         action=arguments.action.concat,
         type=arguments.type.shell_split,
-        default=[])
+        default=[],
+        help='run tests located in specific directories and/or files '
+             '(implies --test and/or --validation-test)')
+    run_tests_group.add_argument(
+        '-o',
+        action='store_const',
+        const=True,
+        dest='test_optimized',
+        help='run the test suite in optimized mode too (implies --test)')
+    run_tests_group.add_argument(
+        '--test-optimized',
+        action=arguments.action.enable,
+        help='run the test suite in optimized mode too (implies --test)')
+    run_tests_group.add_argument(
+        '-s',
+        action='store_const',
+        const=True,
+        dest='test_optimize_for_size',
+        help='run the test suite in optimize for size mode too '
+             '(implies --test)')
+    run_tests_group.add_argument(
+        '--test-optimize-for-size',
+        action=arguments.action.enable,
+        help='run the test suite in optimize for size mode too '
+             '(implies --test)')
+    run_tests_group.add_argument(
+        '--long-test',
+        action=arguments.action.enable,
+        help='run the long test suite')
+    run_tests_group.add_argument(
+        '--host-test',
+        action=arguments.action.enable,
+        help='run executable tests on host devices (such as iOS or tvOS)')
+    run_tests_group.add_argument(
+        '-B', '--benchmark',
+        action='store_true',
+        help='run the Swift Benchmark Suite after building')
+    run_tests_group.add_argument(
+        '--benchmark-num-o-iterations',
+        type=int,
+        default=3,
+        metavar='N',
+        help='if the Swift Benchmark Suite is run after building, run N '
+             'iterations with -O')
+    run_tests_group.add_argument(
+        '--benchmark-num-onone-iterations',
+        type=int,
+        default=3,
+        metavar='N',
+        help='if the Swift Benchmark Suite is run after building, run N '
+             'iterations with -Onone')
+    run_tests_group.add_argument(
+        '--skip-test-osx',
+        action=arguments.action.disable,
+        dest='test_osx',
+        help='skip testing Swift stdlibs for Mac OS X')
+    run_tests_group.add_argument(
+        '--skip-test-linux',
+        action=arguments.action.disable,
+        dest='test_linux',
+        help='skip testing Swift stdlibs for Linux')
+    run_tests_group.add_argument(
+        '--skip-test-freebsd',
+        action=arguments.action.disable,
+        dest='test_freebsd',
+        help='skip testing Swift stdlibs for FreeBSD')
+    run_tests_group.add_argument(
+        '--skip-test-cygwin',
+        action=arguments.action.disable,
+        dest='test_cygwin',
+        help='skip testing Swift stdlibs for Cygwin')
 
-    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=[])
+    # -------------------------------------------------------------------------
+    run_build_group = parser.add_argument_group(
+        title='Run build')
+    run_build_group.add_argument(
+        '--build-swift-dynamic-stdlib',
+        action=arguments.action.enable,
+        default=True,
+        help='build dynamic variants of the Swift standard library')
+    run_build_group.add_argument(
+        '--build-swift-static-stdlib',
+        action=arguments.action.enable,
+        help='build static variants of the Swift standard library')
+    run_build_group.add_argument(
+        '--build-swift-dynamic-sdk-overlay',
+        action=arguments.action.enable,
+        default=True,
+        help='build dynamic variants of the Swift SDK overlay')
+    run_build_group.add_argument(
+        '--build-swift-static-sdk-overlay',
+        action=arguments.action.enable,
+        help='build static variants of the Swift SDK overlay')
+    run_build_group.add_argument(
+        '--build-swift-stdlib-unittest-extra',
+        action=arguments.action.enable,
+        help='Build optional StdlibUnittest components')
+    run_build_group.add_argument(
+        '-S', '--skip-build',
+        action='store_true',
+        help='generate build directory only without building')
+    run_build_group.add_argument(
+        '--skip-build-linux',
+        action=arguments.action.disable,
+        dest='build_linux',
+        help='skip building Swift stdlibs for Linux')
+    run_build_group.add_argument(
+        '--skip-build-freebsd',
+        action=arguments.action.disable,
+        dest='build_freebsd',
+        help='skip building Swift stdlibs for FreeBSD')
+    run_build_group.add_argument(
+        '--skip-build-cygwin',
+        action=arguments.action.disable,
+        dest='build_cygwin',
+        help='skip building Swift stdlibs for Cygwin')
+    run_build_group.add_argument(
+        '--skip-build-osx',
+        action=arguments.action.disable,
+        dest='build_osx',
+        help='skip building Swift stdlibs for MacOSX')
 
-    parser.add_argument(
-        "--verbose-build",
-        help="print the commands executed during the build",
-        action=arguments.action.enable)
+    run_build_group.add_argument(
+        '--skip-build-ios',
+        action=arguments.action.disable,
+        dest='build_ios',
+        help='skip building Swift stdlibs for iOS')
+    run_build_group.add_argument(
+        '--skip-build-ios-device',
+        action=arguments.action.disable,
+        dest='build_ios_device',
+        help='skip building Swift stdlibs for iOS devices '
+             '(i.e. build simulators only)')
+    run_build_group.add_argument(
+        '--skip-build-ios-simulator',
+        action=arguments.action.disable,
+        dest='build_ios_simulator',
+        help='skip building Swift stdlibs for iOS simulator '
+             '(i.e. build devices only)')
 
-    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')
+    run_build_group.add_argument(
+        '--skip-build-tvos',
+        action=arguments.action.disable,
+        dest='build_tvos',
+        help='skip building Swift stdlibs for tvOS')
+    run_build_group.add_argument(
+        '--skip-build-tvos-device',
+        action=arguments.action.disable,
+        dest='build_tvos_device',
+        help='skip building Swift stdlibs for tvOS devices '
+             '(i.e. build simulators only)')
+    run_build_group.add_argument(
+        '--skip-build-tvos-simulator',
+        action=arguments.action.disable,
+        dest='build_tvos_simulator',
+        help='skip building Swift stdlibs for tvOS simulator '
+             '(i.e. build devices only)')
 
-    parser.add_argument(
-        "--clang-profile-instr-use",
-        help="profile file to use for clang PGO",
-        metavar="PATH")
+    run_build_group.add_argument(
+        '--skip-build-watchos',
+        action=arguments.action.disable,
+        dest='build_watchos',
+        help='skip building Swift stdlibs for watchOS')
+    run_build_group.add_argument(
+        '--skip-build-watchos-device',
+        action=arguments.action.disable,
+        dest='build_watchos_device',
+        help='skip building Swift stdlibs for watchOS devices '
+             '(i.e. build simulators only)')
+    run_build_group.add_argument(
+        '--skip-build-watchos-simulator',
+        action=arguments.action.disable,
+        dest='build_watchos_simulator',
+        help='skip building Swift stdlibs for watchOS simulator '
+             '(i.e. build devices only)')
 
-    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'])
+    run_build_group.add_argument(
+        '--skip-build-android',
+        action=arguments.action.disable,
+        dest='build_android',
+        help='skip building Swift stdlibs for Android')
 
-    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'])
+    run_build_group.add_argument(
+        '--skip-build-benchmarks',
+        action=arguments.action.disable,
+        dest='build_benchmarks',
+        help='skip building Swift Benchmark Suite')
 
-    parser.add_argument("--enable-sil-ownership",
-                        help="Enable the SIL ownership model",
-                        action='store_true')
+    run_build_group.add_argument(
+        '--build-external-benchmarks',
+        action=arguments.action.enable,
+        dest='build_external_benchmarks',
+        help='skip building Swift Benchmark Suite')
 
-    parser.add_argument("--force-optimized-typechecker",
-                        help="Force the type checker to be built with "
-                        "optimization",
-                        action='store_true')
+    # -------------------------------------------------------------------------
+    skip_test_group = parser.add_argument_group(
+        title='Skip testing specified targets')
+    skip_test_group.add_argument(
+        '--skip-test-ios',
+        action=arguments.action.disable,
+        dest='test_ios',
+        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',
+        action=arguments.action.disable,
+        dest='test_ios_simulator',
+        help='skip testing iOS simulator targets')
+    skip_test_group.add_argument(
+        '--skip-test-ios-32bit-simulator',
+        action=arguments.action.disable,
+        dest='test_ios_32bit_simulator',
+        help='skip testing iOS 32 bit simulator targets')
+    skip_test_group.add_argument(
+        '--skip-test-ios-host',
+        action=arguments.action.disable,
+        dest='test_ios_host',
+        help='skip testing iOS device targets on the host machine (the phone '
+             'itself)')
+    skip_test_group.add_argument(
+        '--skip-test-tvos',
+        action=arguments.action.disable,
+        dest='test_tvos',
+        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',
+        action=arguments.action.disable,
+        dest='test_tvos_simulator',
+        help='skip testing tvOS simulator targets')
+    skip_test_group.add_argument(
+        '--skip-test-tvos-host',
+        action=arguments.action.disable,
+        dest='test_tvos_host',
+        help='skip testing tvOS device targets on the host machine (the TV '
+             'itself)')
+    skip_test_group.add_argument(
+        '--skip-test-watchos',
+        action=arguments.action.disable,
+        dest='test_watchos',
+        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',
+        action=arguments.action.disable,
+        dest='test_watchos_simulator',
+        help='skip testing watchOS simulator targets')
+    skip_test_group.add_argument(
+        '--skip-test-watchos-host',
+        action=arguments.action.disable,
+        dest='test_watchos_host',
+        help='skip testing watchOS device targets on the host machine (the '
+             'watch itself)')
+    skip_test_group.add_argument(
+        '--skip-test-android-host',
+        action=arguments.action.disable,
+        dest='test_android_host',
+        help='skip testing Android device targets on the host machine (the '
+             'phone itself)')
 
-    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)
+    # -------------------------------------------------------------------------
+    in_group('Build settings specific for LLVM')
 
-    parser.add_argument(
-        "--lit-args",
-        help="lit args to use when testing",
-        metavar="LITARGS",
-        default="-sv")
+    option('--llvm-targets-to-build', store,
+           default='X86;ARM;AArch64;PowerPC;SystemZ;Mips',
+           help='LLVM target generators to build')
 
-    parser.add_argument(
-        "--coverage-db",
-        help="coverage database to use when prioritizing testing",
-        metavar="PATH")
+    # -------------------------------------------------------------------------
+    in_group('Build settings for Android')
 
-    return parser
+    option('--android-ndk', store_path,
+           help='An absolute path to the NDK that will be used as a libc '
+                'implementation for Android builds')
+
+    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')
+
+    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')
+
+    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 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..f4b8315
--- /dev/null
+++ b/utils/build_swift/tests/argparse/test_actions.py
@@ -0,0 +1,419 @@
+# 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)
+
+
+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..accdd72
--- /dev/null
+++ b/utils/build_swift/tests/argparse/test_types.py
@@ -0,0 +1,175 @@
+# 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 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(AssertionError):
+            path_type(__file__)
+
+        with self.assertRaises(AssertionError):
+            path_type('/nonsensisal/path/')
+            path_type('~/not-a-real/path to a 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()
+
+        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()
+
+        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_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..979be6a 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',
@@ -122,11 +117,16 @@
                    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'),
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index d6c57e1..eb422e3 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,32 @@
              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')
+         ]),
 ]
diff --git a/utils/gyb_syntax_support/GenericNodes.py b/utils/gyb_syntax_support/GenericNodes.py
index 2107aac..161f1b5 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,7 @@
     #                    | type-name : protocol-composition-type
     Node('GenericParameter', kind='Syntax',
          children=[
-             Child('TypeIdentifier', kind='TypeIdentifier'),
+             Child('Name', kind='IdentifierToken'),
              Child('Colon', kind='ColonToken',
                    is_optional=True),
              Child('InheritedType', kind='Type',
@@ -55,9 +55,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/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/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_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/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/0130-rdar35632543.swift b/validation-test/compiler_crashers_2_fixed/0130-rdar35632543.swift
new file mode 100644
index 0000000..551a853
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0130-rdar35632543.swift
@@ -0,0 +1,36 @@
+// RUN: %target-swift-frontend %s -emit-ir
+
+public protocol ObservableType {
+  associatedtype E
+}
+
+public protocol SubjectType : ObservableType {
+  associatedtype SubjectObserverType : ObserverType
+}
+
+extension ObservableType {
+  public func multicast<S: SubjectType>(_ subject: S) -> Observable<S.E> {
+    while true {}
+  }
+}
+
+
+extension ObservableType {
+  public func publish() -> Observable<E> {
+    return self.multicast(PublishSubject())
+  }
+}
+
+public class Observable<Element> : ObservableType {
+  public typealias E = Element
+}
+
+public protocol ObserverType {
+  associatedtype E
+}
+
+public final class PublishSubject<Element> : Observable<Element>, SubjectType, ObserverType
+{
+  public typealias SubjectObserverType = PublishSubject<Element>
+}
+
diff --git a/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift b/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift
new file mode 100644
index 0000000..68d72ec
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift
@@ -0,0 +1,28 @@
+// RUN: not %target-swift-frontend %s -typecheck
+
+protocol DC {
+  init()
+}
+
+protocol P {
+  associatedtype A: DC
+
+  func f() -> A
+}
+
+protocol Q: P {
+  associatedtype A
+}
+
+extension Q {
+  func f() -> A { return A() }
+}
+
+struct X<T> { }
+
+extension X: P where T: P {
+  typealias A = T.A
+}
+
+extension X: Q where T: Q {
+}
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/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/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index 66e965b..32d9b54 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -77,6 +77,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 {
@@ -3226,9 +3233,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") {
@@ -3240,9 +3245,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") {
@@ -3327,9 +3330,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") {
@@ -3355,9 +3356,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/Lazy.swift.gyb b/validation-test/stdlib/Lazy.swift.gyb
index aeb39a4..5aea559 100644
--- a/validation-test/stdlib/Lazy.swift.gyb
+++ b/validation-test/stdlib/Lazy.swift.gyb
@@ -38,7 +38,7 @@
   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,7 +121,7 @@
   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)
@@ -533,7 +533,7 @@
 %for (Traversal, ReversedType) in [
 %    ('Forward', None),
 %    ('Bidirectional', 'ReversedCollection'),
-%    ('RandomAccess', 'ReversedRandomAccessCollection')
+%    ('RandomAccess', 'ReversedCollection')
 %]:
 %  TraversalCollection = collectionForTraversal(Traversal)
 
@@ -608,18 +608,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")
   }
@@ -993,7 +995,7 @@
     ExpectType<Base>.test(base)
 
     typealias LazyReversedBase = LazyRandomAccessCollection<
-      ReversedRandomAccessCollection<Base>>
+      ReversedCollection<Base>>
 
     let reversed = base.reversed()
     ExpectType<LazyReversedBase>.test(reversed)
@@ -1372,7 +1374,7 @@
     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)
@@ -1432,7 +1434,7 @@
     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/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 529aa2d..8361851 100644
--- a/validation-test/stdlib/Range.swift.gyb
+++ b/validation-test/stdlib/Range.swift.gyb
@@ -768,7 +768,7 @@
   typealias Collection = CountableClosedRange<MinimalStrideableValue>
   expectCollectionAssociatedTypes(
     collectionType: Collection.self,
-    iteratorType: ClosedRangeIterator<MinimalStrideableValue>.self,
+    iteratorType: IndexingIterator<Collection>.self,
     subSequenceType: RandomAccessSlice<Collection>.self,
     indexType: ClosedRangeIndex<MinimalStrideableValue>.self,
     indexDistanceType: MinimalStrideableValue.Stride.self,
diff --git a/validation-test/stdlib/RangeReplaceable.swift.gyb b/validation-test/stdlib/RangeReplaceable.swift.gyb
index d2c7208..5052074 100644
--- a/validation-test/stdlib/RangeReplaceable.swift.gyb
+++ b/validation-test/stdlib/RangeReplaceable.swift.gyb
@@ -2,6 +2,9 @@
 // RUN: %target-run-simple-swiftgyb
 // REQUIRES: executable_test
 
+// FIXME: rdar://35646292
+// XFAIL: resilient_stdlib
+
 import StdlibUnittest
 import StdlibCollectionUnittest
 
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index 401298c..fcc8cdc 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -331,6 +331,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 +2216,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 +2227,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 +2250,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 +2261,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/String.swift b/validation-test/stdlib/String.swift
index fc0add1..28ec39f 100644
--- a/validation-test/stdlib/String.swift
+++ b/validation-test/stdlib/String.swift
@@ -148,7 +148,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 +166,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 +735,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 +775,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 +861,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 +1281,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 +1495,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 +1509,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 +1525,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 +1542,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 +1555,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 +1572,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 +1589,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 +1617,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 +1638,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 +1655,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 +1665,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 +1691,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 +1707,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 +1725,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 +1746,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 +1756,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 +1771,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/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 29eae21..7cff62d 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -13,63 +13,14 @@
 // REQUIRES: executable_test
 // REQUIRES: objc_interop
 
+// FIXME: rdar://35814988
+// UNSUPPORTED: CPU=armv7
+// 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 +648,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 +698,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 +748,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)