Merge pull request #18712 from xedin/fix-asan-failure-in-cs

[ConstraintSystem] Don't try to eagerly deallocate fixes
diff --git a/.flake8 b/.flake8
index 1657767..d3728e2 100644
--- a/.flake8
+++ b/.flake8
@@ -23,6 +23,7 @@
            ./utils/recursive-lipo,
            ./utils/round-trip-syntax-test,
            ./utils/rth,
+           ./utils/run-remote,
            ./utils/run-test,
            ./utils/scale-test,
            ./utils/submit-benchmark-results,
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
index 1309040..5adc020 100644
--- a/CODE_OWNERS.TXT
+++ b/CODE_OWNERS.TXT
@@ -20,7 +20,7 @@
 N: Erik Eckstein
 E: eeckstein@apple.com
 G: eeckstein
-D: SILOptimizer
+D: SILOptimizer, Swift Benchmark Suite
 
 N: Xi Ge
 E: xi_ge@apple.com
@@ -42,11 +42,6 @@
 G: akyrtzi
 D: IDE, Index, SourceKit, swift-ide-test
 
-N: Luke Larson
-E: llarson@apple.com
-G: lplarson
-D: Swift Benchmark Suite
-
 N: John McCall
 E: rjmccall@apple.com
 G: rjmccall
diff --git a/README.md b/README.md
index 133c3b5..cb893db 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,7 @@
 |**[Ubuntu 16.04 ](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/ppc64le_ubuntu_16_04.json)** | PPC64LE |[![Build Status](https://ci-external.swift.org/job/oss-swift-4.1-RA-linux-ubuntu-16.04-ppc64le/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-4.1-RA-linux-ubuntu-16.04-ppc64le)|
 |**[Ubuntu 16.04 ](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/aarch64_ubuntu_16.04.json)** | AArch64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-aarch64/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-aarch64)|
 |**[Ubuntu 16.04 (Android)](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/x86_64_ubuntu_16_04_LTS_android.json)** | x86_64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android)|
+|**[macOS 10.13 (TensorFlow)](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/x86_64_macos_high_sierra_tensorflow.json)** | x86_64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-macOS-tensorflow/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-macOS-tensorflow)|
 
 
 **Welcome to Swift!**
diff --git a/benchmark/scripts/bench_code_size.py b/benchmark/scripts/bench_code_size.py
index 42e987d..0ed8a16 100755
--- a/benchmark/scripts/bench_code_size.py
+++ b/benchmark/scripts/bench_code_size.py
@@ -30,13 +30,17 @@
     argparser = argparse.ArgumentParser()
     argparser.add_argument(
         '-O', action='append_const', const='O', dest='opt_levels',
-        help='test -O benchmarks')
+        help='report code size of -O benchmarks')
     argparser.add_argument(
         '-Osize', action='append_const', const='Osize', dest='opt_levels',
-        help='test -Osize benchmarks')
+        help='report code size of -Osize benchmarks')
     argparser.add_argument(
         '-Onone', action='append_const', const='Onone', dest='opt_levels',
-        help='test -Onone benchmarks')
+        help='report code size of -Onone benchmarks')
+    argparser.add_argument(
+        '-swiftlibs', action='append_const', const='swiftlibs',
+        dest='opt_levels',
+        help='report code size of swift dylibs')
     argparser.add_argument(
         'oldbuilddir', nargs=1, type=str,
         help='old benchmark build directory')
@@ -62,10 +66,13 @@
     old_logf = open(log_filename(old_dir), 'w')
     new_logf = open(log_filename(new_dir), 'w')
 
-    files = glob.glob(os.path.join(old_dir, opt_level + '-*' + platform + '*',
-                                   '*.o'))
-    files += glob.glob(os.path.join(old_dir, 'lib', 'swift', platform,
-                                    '*.dylib'))
+    if opt_level == 'swiftlibs':
+        files = glob.glob(os.path.join(old_dir, 'lib', 'swift', platform,
+                                       '*.dylib'))
+    else:
+        files = glob.glob(os.path.join(old_dir,
+                                       opt_level + '-*' + platform + '*',
+                                       '*.o'))
 
     idx = 1
     for oldfile in files:
diff --git a/benchmark/scripts/compare_perf_tests.py b/benchmark/scripts/compare_perf_tests.py
index 4243dee..2865df5 100755
--- a/benchmark/scripts/compare_perf_tests.py
+++ b/benchmark/scripts/compare_perf_tests.py
@@ -220,11 +220,13 @@
     `values()` into report table. Supported formats are: `markdown` (used for
     displaying benchmark results on GitHub), `git` and `html`.
     """
-    def __init__(self, comparator, old_branch, new_branch, changes_only):
+    def __init__(self, comparator, old_branch, new_branch, changes_only,
+                 single_table=False):
         self.comparator = comparator
         self.old_branch = old_branch
         self.new_branch = new_branch
         self.changes_only = changes_only
+        self.single_table = single_table
 
     MARKDOWN_DETAIL = """
 <details {3}>
@@ -266,6 +268,7 @@
 
     def _formatted_text(self, ROW, HEADER_SEPARATOR, DETAIL):
         widths = self._column_widths()
+        self.header_printed = False
 
         def justify_columns(contents):
             return tuple([c.ljust(w) for w, c in zip(widths, contents)])
@@ -285,12 +288,24 @@
                 row(format_columns(result_comparison.values(), is_strong))
                 for result_comparison in results
             ]
-            return ('' if not rows else
-                    DETAIL.format(*[
-                        title, len(results),
-                        (header(results[0].header) + ''.join(rows)),
-                        ('open' if is_open else '')
-                    ]))
+            if not rows:
+                return ''
+
+            if self.single_table:
+                t = ''
+                if not self.header_printed:
+                    t += header(results[0].header)
+                    self.header_printed = True
+                t += row(('**' + title + '**', '', '', '', ''))
+                t += ''.join(rows)
+                return t
+
+            return DETAIL.format(
+                *[
+                    title, len(results),
+                    (header(results[0].header) + ''.join(rows)),
+                    ('open' if is_open else '')
+                ])
 
         return ''.join([
             # FIXME print self.old_branch, self.new_branch
@@ -393,6 +408,10 @@
     parser.add_argument('--output', help='Output file name')
     parser.add_argument('--changes-only',
                         help='Output only affected tests', action='store_true')
+    parser.add_argument(
+        '--single-table',
+        help='Combine data in a single table in git and markdown formats',
+        action='store_true')
     parser.add_argument('--new-branch',
                         help='Name of the new branch', default='NEW_MIN')
     parser.add_argument('--old-branch',
@@ -408,7 +427,7 @@
     comparator = TestComparator(args.old_file, args.new_file,
                                 args.delta_threshold)
     formatter = ReportFormatter(comparator, args.old_branch, args.new_branch,
-                                args.changes_only)
+                                args.changes_only, args.single_table)
     formats = {
         'markdown': formatter.markdown,
         'git': formatter.git,
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 8fed6d4..347e697 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -4714,7 +4714,9 @@
 ````````````````
 ::
 
-  sil-instruction ::= 'convert_function' sil-operand 'to' sil-type
+  sil-instruction ::= 'convert_function' sil-operand 'to'
+                      ('[' 'without_actually_escaping' ']')?
+                      sil-type
 
   %1 = convert_function %0 : $T -> U to $T' -> U'
   // %0 must be of a function type $T -> U ABI-compatible with $T' -> U'
@@ -4744,6 +4746,18 @@
 convert from an escaping to a ``@noescape`` thick function type use
 ``convert_escape_to_noescape``.
 
+With the ``without_actually_escaping`` attribute, the
+``convert_function`` may be used to convert a non-escaping closure
+into an escaping function type. This attribute must be present
+whenever the closure operand has an unboxed capture (via
+@inout_aliasable) *and* the resulting function type is escaping. (This
+only happens as a result of withoutActuallyEscaping()). If the
+attribute is present then the resulting function type must be
+escaping, but the operand's function type may or may not be
+@noescape. Note that a non-escaping closure may have unboxed captured
+even though its SIL function type is "escaping".
+
+
 convert_escape_to_noescape
 ```````````````````````````
 ::
diff --git a/docs/Testing.md b/docs/Testing.md
index 4ee3dfd..7e8c7da 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -80,7 +80,7 @@
 useful features, like timing tests and providing a timeout. Check these features
 out with ``lit.py -h``. We document some of the more useful ones below:
 
-##### Extra lit.py invocation options
+##### Standard lit.py invocation options
 
 * ``-s`` reduces the amount of output that lit shows.
 * ``-v`` causes a test's commandline and output to be printed if the test fails.
@@ -100,6 +100,9 @@
   running a single test (in seconds). 0 (the default means no time limit.
 * ``--max-failures=<MAXFAILURES>`` stops execution after ``MAXFAILURES`` number
   of failures.
+
+##### Swift-specific testing options
+
 * ``--param gmalloc`` will run all tests under Guard Malloc (macOS only). See
   ``man libgmalloc`` for more information.
 * ``--param swift-version=<MAJOR>`` overrides the default Swift language
@@ -111,6 +114,22 @@
   mentioned above. Again, it's best to get the invocation from the existing
   build system targets and modify it rather than constructing it yourself.
 
+##### Remote testing options
+
+* ``--param remote_run_host=[USER@]<HOST>[:PORT]`` causes execution tests that
+  would normally be run on the host (via the ``%target-run`` substitutions
+  described below) to be run over SSH on another machine instead, using the
+  `remote-run` tool in the `utils` directory. Requires that `remote_run_tmpdir`
+  also be provided.
+* ``--param remote_run_tmpdir=<PATH>`` specifies the scratch directory to be
+  used on the remote machine when testing with `remote_run_host`.
+* ``--param remote_run_identity=<FILE>`` provides an SSH private key to be used
+  when testing with `remote_run_host`. (`remote-run` does not support
+  passwords.)
+* ``--param remote_run_skip_upload_stdlib`` assumes that the standard library
+  binaries have already been uploaded to `remote_run_tmpdir` and are up to date.
+  This is meant for repeat runs and probably shouldn't be used in automation.
+
 #### CMake
 
 Although it is not recommended for day-to-day contributions, it is also
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index 3009fdc..47b4198 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -72,13 +72,15 @@
   typedef std::pair<Type, ProtocolDecl *> Entry;
 
 private:
-  llvm::SmallVector<Entry, 2> path;
+  ArrayRef<Entry> path;
+
+  ConformanceAccessPath(ArrayRef<Entry> path) : path(path) {}
 
   friend class GenericSignature;
 
 public:
-  typedef llvm::SmallVector<Entry, 2>::const_iterator iterator;
-  typedef llvm::SmallVector<Entry, 2>::const_iterator const_iterator;
+  typedef const Entry *const_iterator;
+  typedef const_iterator iterator;
 
   const_iterator begin() const { return path.begin(); }
   const_iterator end() const { return path.end(); }
@@ -133,6 +135,13 @@
   /// Retrieve the generic signature builder for the given generic signature.
   GenericSignatureBuilder *getGenericSignatureBuilder();
 
+  void buildConformanceAccessPath(
+      SmallVectorImpl<ConformanceAccessPath::Entry> &path,
+      ArrayRef<Requirement> reqs,
+      const void /*GenericSignatureBuilder::RequirementSource*/ *source,
+      ProtocolDecl *conformingProto, Type rootType,
+      ProtocolDecl *requirementSignatureProto);
+
   friend class ArchetypeType;
 
 public:
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index dced5ea..160d1d5 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -22,6 +22,7 @@
 
 #include "swift/AST/Decl.h"
 #include "swift/AST/DiagnosticEngine.h"
+#include "swift/AST/GenericSignature.h"
 #include "swift/AST/Identifier.h"
 #include "swift/AST/ProtocolConformanceRef.h"
 #include "swift/AST/Types.h"
@@ -45,7 +46,6 @@
 class DeclContext;
 class DependentMemberType;
 class GenericParamList;
-class GenericSignature;
 class GenericSignatureBuilder;
 class GenericTypeParamType;
 class LazyResolver;
@@ -278,6 +278,10 @@
     /// Cached nested-type information, which contains the best declaration
     /// for a given name.
     llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
+
+    /// Cached access paths.
+    llvm::SmallDenseMap<const ProtocolDecl *, ConformanceAccessPath, 8>
+        conformanceAccessPathCache;
   };
 
   friend class RequirementSource;
diff --git a/include/swift/Basic/OwnedString.h b/include/swift/Basic/OwnedString.h
index e7bb761c..ef2b0be 100644
--- a/include/swift/Basic/OwnedString.h
+++ b/include/swift/Basic/OwnedString.h
@@ -22,117 +22,89 @@
 
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/TrailingObjects.h"
 
 using llvm::StringRef;
 
 namespace swift {
 
-enum class StringOwnership {
-  /// An OwnedString holds a weak reference to the underlying string storage
-  /// and will never attempt to free it.
-  Unowned,
-
-  /// An OwnedString has its own copy of the underlying string storage and
-  /// will free the storage upon its destruction.
-  Copied,
-};
-
 /// Holds a string - either statically allocated or dynamically allocated
 /// and owned by this type.
 class OwnedString {
-  const char *Data;
-  size_t Length;
-  StringOwnership Ownership = StringOwnership::Unowned;
-
-  void release() {
-    if (Ownership == StringOwnership::Copied)
-      free(const_cast<char *>(Data));
-  }
-
-  void initialize(const char* Data, size_t Length, StringOwnership Ownership) {
-    this->Length = Length;
-    this->Ownership = Ownership;
-    if (Ownership == StringOwnership::Copied && Data) {
-      char *substring = static_cast<char *>(malloc(Length + 1));
-      assert(substring && "expected successful malloc of copy");
-
-      memcpy(substring, Data, Length);
-      substring[Length] = '\0';
-
-      this->Data = substring;
+  /// An owner that keeps the buffer of a ref counted \c OwnedString alive.
+  class TextOwner final : public llvm::ThreadSafeRefCountedBase<TextOwner>,
+                          public llvm::TrailingObjects<TextOwner, char> {
+    TextOwner(StringRef Text) {
+      std::uninitialized_copy(Text.begin(), Text.end(),
+                              getTrailingObjects<char>());
     }
-    else
-      this->Data = Data;
-  }
-  OwnedString(const char* Data, size_t Length, StringOwnership Ownership) {
-    initialize(Data, Length, Ownership);
-  }
+
+  public:
+    static TextOwner *make(StringRef Text) {
+      auto size = totalSizeToAlloc<char>(Text.size());
+      void *data = ::operator new(size);
+      return new (data) TextOwner(Text);
+    }
+
+    const char *getText() const { return getTrailingObjects<char>(); }
+  };
+
+  /// The text this owned string represents
+  StringRef Text;
+
+  /// In case of a ref counted string an owner that keeps the buffer \c Text
+  /// references alive.
+  llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr;
+
+  OwnedString(StringRef Text, llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr)
+      : Text(Text), OwnedPtr(OwnedPtr) {}
+
 public:
-  OwnedString(): OwnedString(nullptr, 0, StringOwnership::Unowned) {}
+  OwnedString() : OwnedString(/*Text=*/StringRef(), /*OwnedPtr=*/nullptr) {}
 
-  OwnedString(const char *Data, size_t Length):
-    OwnedString(Data, Length, StringOwnership::Copied) {}
+  /// Create a ref counted \c OwnedString that is initialized with the text of
+  /// the given \c StringRef.
+  OwnedString(StringRef Str) : OwnedString(makeRefCounted(Str)) {}
 
-  OwnedString(StringRef Str) : OwnedString(Str.data(), Str.size()) {}
+  /// Create a ref counted \c OwnedString that is initialized with the text of
+  /// the given buffer.
+  OwnedString(const char *Str) : OwnedString(StringRef(Str)) {}
 
-  OwnedString(const char *Data) : OwnedString(StringRef(Data)) {}
-
-  OwnedString(const OwnedString &Other):
-    OwnedString(Other.Data, Other.Length, Other.Ownership) {}
-
-  OwnedString(OwnedString &&Other): Data(Other.Data), Length(Other.Length),
-      Ownership(Other.Ownership) {
-    Other.Data = nullptr;
-    Other.Ownership = StringOwnership::Unowned;
+  /// Create an \c OwnedString that references the given string. The
+  /// \c OwnedString will not take ownership of that buffer and will assume that
+  /// the buffer outlives its lifetime.
+  static OwnedString makeUnowned(StringRef Str) {
+    return OwnedString(Str, /*OwnedPtr=*/nullptr);
   }
 
-  OwnedString& operator=(const OwnedString &Other) {
-    if (&Other != this) {
-      release();
-      initialize(Other.Data, Other.Length, Other.Ownership);
+  /// Create an \c OwnedString that keeps its contents in a reference counted
+  /// buffer. The contents of \p Str will be copied initially and are allowed to
+  /// be disposed after the \c OwnedString has been created.
+  static OwnedString makeRefCounted(StringRef Str) {
+    if (Str.empty()) {
+      // Copying an empty string doesn't make sense. Just create an unowned
+      // string that points to the empty string.
+      return makeUnowned(Str);
+    } else {
+      llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr(TextOwner::make(Str));
+      return OwnedString(StringRef(OwnedPtr->getText(), Str.size()),
+                         std::move(OwnedPtr));
     }
-    return *this;
-  }
-
-  OwnedString& operator=(OwnedString &&Other) {
-    if (&Other != this) {
-      release();
-      this->Data = Other.Data;
-      this->Length = Other.Length;
-      this->Ownership = Other.Ownership;
-      Other.Ownership = StringOwnership::Unowned;
-      Other.Data = nullptr;
-    }
-    return *this;
-  }
-
-  OwnedString copy() const {
-    return OwnedString(Data, Length, StringOwnership::Copied);
   }
 
   /// Returns the length of the string in bytes.
-  size_t size() const {
-    return Length;
-  }
+  size_t size() const { return Text.size(); }
 
   /// Returns true if the length is 0.
-  bool empty() const {
-    return Length == 0;
-  }
+  bool empty() const { return size() == 0; }
 
   /// Returns a StringRef to the underlying data. No copy is made and no
   /// ownership changes take place.
-  StringRef str() const {
-    return StringRef { Data, Length };
-  }
+  StringRef str() const { return Text; }
 
   bool operator==(const OwnedString &Right) const {
     return str() == Right.str();
   }
-
-  ~OwnedString() {
-    release();
-  }
 };
 
 } // end namespace swift
diff --git a/include/swift/SIL/InstructionUtils.h b/include/swift/SIL/InstructionUtils.h
index 5d8891d9..9d15354 100644
--- a/include/swift/SIL/InstructionUtils.h
+++ b/include/swift/SIL/InstructionUtils.h
@@ -86,6 +86,9 @@
 /// copies the value of its first operand, possibly changing its type or
 /// ownership state, but otherwise having no effect.
 ///
+/// The returned instruction may have additional "incidental" operands;
+/// mark_dependence for example.
+///
 /// This is useful for checking all users of a value to verify that the value is
 /// only used in recognizable patterns without otherwise "escaping". These are
 /// instructions that the use-visitor can recurse into. Note that the value's
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 568bc9d..901d95b 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -886,9 +886,11 @@
   }
 
   ConvertFunctionInst *createConvertFunction(SILLocation Loc, SILValue Op,
-                                             SILType Ty) {
-    return insert(ConvertFunctionInst::create(
-        getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
+                                             SILType Ty,
+                                             bool WithoutActuallyEscaping) {
+    return insert(ConvertFunctionInst::create(getSILDebugLocation(Loc), Op, Ty,
+                                              getFunction(), C.OpenedArchetypes,
+                                              WithoutActuallyEscaping));
   }
 
   ConvertEscapeToNoEscapeInst *
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index f12e147..f67aee9 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -1020,10 +1020,10 @@
 void
 SILCloner<ImplClass>::visitConvertFunctionInst(ConvertFunctionInst *Inst) {
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
-  doPostProcess(Inst,
-    getBuilder().createConvertFunction(getOpLocation(Inst->getLoc()),
-                                       getOpValue(Inst->getOperand()),
-                                       getOpType(Inst->getType())));
+  doPostProcess(
+      Inst, getBuilder().createConvertFunction(
+                getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
+                getOpType(Inst->getType()), Inst->withoutActuallyEscaping()));
 }
 
 template <typename ImplClass>
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index a6b46e4..fa30426 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -231,6 +231,14 @@
   /// serialization.
   bool WasDeserializedCanonical = false;
 
+  /// True if this is a reabstraction thunk of escaping function type whose
+  /// single argument is a potentially non-escaping closure. This is an escape
+  /// hatch to allow non-escaping functions to be stored or passed as an
+  /// argument with escaping function type. The thunk argument's function type
+  /// is not necessarily @noescape. The only relevant aspect of the argument is
+  /// that it may have unboxed capture (i.e. @inout_aliasable parameters).
+  bool IsWithoutActuallyEscapingThunk = false;
+
   static void
   validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
                         const GenericSpecializationInformation *genericInfo) {
@@ -385,6 +393,18 @@
     WasDeserializedCanonical = val;
   }
 
+  /// Returns true if this is a reabstraction thunk of escaping function type
+  /// whose single argument is a potentially non-escaping closure. i.e. the
+  /// thunks' function argument may itself have @inout_aliasable parameters.
+  bool isWithoutActuallyEscapingThunk() const {
+    return IsWithoutActuallyEscapingThunk;
+  }
+
+  void setWithoutActuallyEscapingThunk(bool val = true) {
+    assert(!val || isThunk() == IsReabstractionThunk);
+    IsWithoutActuallyEscapingThunk = val;
+  }
+
   /// Returns the calling convention used by this entry point.
   SILFunctionTypeRepresentation getRepresentation() const {
     return getLoweredFunctionType()->getRepresentation();
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 4965463..d5cc78b 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -3957,9 +3957,12 @@
   friend SILBuilder;
 
   ConvertFunctionInst(SILDebugLocation DebugLoc, SILValue Operand,
-                      ArrayRef<SILValue> TypeDependentOperands, SILType Ty)
+                      ArrayRef<SILValue> TypeDependentOperands, SILType Ty,
+                      bool WithoutActuallyEscaping)
       : UnaryInstructionWithTypeDependentOperandsBase(
             DebugLoc, Operand, TypeDependentOperands, Ty) {
+    SILInstruction::Bits.ConvertFunctionInst.WithoutActuallyEscaping =
+        WithoutActuallyEscaping;
     assert((Operand->getType().castTo<SILFunctionType>()->isNoEscape() ==
                 Ty.castTo<SILFunctionType>()->isNoEscape() ||
             Ty.castTo<SILFunctionType>()->getRepresentation() !=
@@ -3967,9 +3970,24 @@
            "Change of escapeness is not ABI compatible");
   }
 
-  static ConvertFunctionInst *
-  create(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty,
-         SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes);
+  static ConvertFunctionInst *create(SILDebugLocation DebugLoc,
+                                     SILValue Operand, SILType Ty,
+                                     SILFunction &F,
+                                     SILOpenedArchetypesState &OpenedArchetypes,
+                                     bool WithoutActuallyEscaping);
+
+public:
+  /// Returns `true` if this converts a non-escaping closure into an escaping
+  /// function type. `True` must be returned whenever the closure operand has an
+  /// unboxed capture (via @inout_aliasable) *and* the resulting function type
+  /// is escaping. (This only happens as a result of
+  /// withoutActuallyEscaping()). If `true` is returned, then the resulting
+  /// function type must be escaping, but the operand's function type may or may
+  /// not be @noescape. Note that a non-escaping closure may have unboxed
+  /// captured even though its SIL function type is "escaping".
+  bool withoutActuallyEscaping() const {
+    return SILInstruction::Bits.ConvertFunctionInst.WithoutActuallyEscaping;
+  }
 };
 
 /// ConvertEscapeToNoEscapeInst - Change the type of a escaping function value
diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h
index b483cf0..feaa596 100644
--- a/include/swift/SIL/SILNode.h
+++ b/include/swift/SIL/SILNode.h
@@ -315,7 +315,8 @@
     IsInvariant : 1
   );
 
-  UIWTDOB_BITFIELD_EMPTY(ConvertFunctionInst, ConversionInst);
+  UIWTDOB_BITFIELD(ConvertFunctionInst, ConversionInst, 1,
+                   WithoutActuallyEscaping : 1);
   UIWTDOB_BITFIELD_EMPTY(PointerToThinFunctionInst, ConversionInst);
   UIWTDOB_BITFIELD_EMPTY(UnconditionalCheckedCastInst, ConversionInst);
   UIWTDOB_BITFIELD_EMPTY(UpcastInst, ConversionInst);
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 162f7ba..de4741d 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// 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.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 435; // Last change: serialize new-style function parameters
+const uint16_t VERSION_MINOR = 436; // Last change: without_actually_escaping.
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index 6ff2d92..b6e2c19 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -404,12 +404,17 @@
     return static_cast<tok>(Bits.Token.TokenKind);
   }
 
-  /// Return the text of the token.
-  StringRef getTokenText() const {
+  /// Return the text of the token as an \c OwnedString. Keeping a reference to
+  /// this string will keep it alive even if the syntax node gets freed.
+  OwnedString getOwnedTokenText() const {
     assert(isToken());
-    return getTrailingObjects<OwnedString>()->str();
+    return *getTrailingObjects<OwnedString>();
   }
 
+  /// Return the text of the token as a reference. The referenced buffer may
+  /// disappear when the syntax node gets freed.
+  StringRef getTokenText() const { return getOwnedTokenText().str(); }
+
   /// Return the leading trivia list of the token.
   ArrayRef<TriviaPiece> getLeadingTrivia() const {
     assert(isToken());
@@ -434,7 +439,7 @@
   /// trivia instead.
   RC<RawSyntax>
   withLeadingTrivia(ArrayRef<TriviaPiece> NewLeadingTrivia) const {
-    return make(getTokenKind(), getTokenText(), NewLeadingTrivia,
+    return make(getTokenKind(), getOwnedTokenText(), NewLeadingTrivia,
                 getTrailingTrivia(), getPresence());
   }
 
@@ -446,7 +451,7 @@
   /// trivia instead.
   RC<RawSyntax>
   withTrailingTrivia(ArrayRef<TriviaPiece> NewTrailingTrivia) const {
-    return make(getTokenKind(), getTokenText(), getLeadingTrivia(),
+    return make(getTokenKind(), getOwnedTokenText(), getLeadingTrivia(),
                 NewTrailingTrivia, getPresence());
   }
 
diff --git a/include/swift/Syntax/Serialization/SyntaxDeserialization.h b/include/swift/Syntax/Serialization/SyntaxDeserialization.h
index 166517e..4db404d 100644
--- a/include/swift/Syntax/Serialization/SyntaxDeserialization.h
+++ b/include/swift/Syntax/Serialization/SyntaxDeserialization.h
@@ -162,9 +162,9 @@
       StringRef nodeIdString;
       in.mapRequired("id", nodeIdString);
       unsigned nodeId = std::atoi(nodeIdString.data());
-      value =
-          swift::RawSyntax::make(tokenKind, text, leadingTrivia, trailingTrivia,
-                                 presence, /*Arena=*/nullptr, nodeId);
+      value = swift::RawSyntax::make(
+          tokenKind, swift::OwnedString::makeRefCounted(text), leadingTrivia,
+          trailingTrivia, presence, /*Arena=*/nullptr, nodeId);
     } else {
       swift::SyntaxKind kind;
       in.mapRequired("kind", kind);
diff --git a/include/swift/Syntax/Trivia.h.gyb b/include/swift/Syntax/Trivia.h.gyb
index fd5348f..28fae87 100644
--- a/include/swift/Syntax/Trivia.h.gyb
+++ b/include/swift/Syntax/Trivia.h.gyb
@@ -496,7 +496,8 @@
 % else:
       StringRef text;
       in.mapRequired("value", text);
-      return swift::syntax::TriviaPiece(kind, text);
+      return swift::syntax::TriviaPiece(
+          kind, swift::OwnedString::makeRefCounted(text));
 % end
       break;
     }
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 53e7699..884ef0c 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -817,9 +817,147 @@
   return bestSource;
 }
 
-ConformanceAccessPath GenericSignature::getConformanceAccessPath(
-                                                       Type type,
-                                                       ProtocolDecl *protocol) {
+void GenericSignature::buildConformanceAccessPath(
+    SmallVectorImpl<ConformanceAccessPath::Entry> &path,
+    ArrayRef<Requirement> reqs, const void *opaqueSource,
+    ProtocolDecl *conformingProto, Type rootType,
+    ProtocolDecl *requirementSignatureProto) {
+  auto *source = reinterpret_cast<const RequirementSource *>(opaqueSource);
+  // Each protocol requirement is a step along the path.
+  if (source->isProtocolRequirement()) {
+    // If we're expanding for a protocol that had no requirement signature
+    // and have hit the penultimate step, this is the last step
+    // that would occur in the requirement signature.
+    Optional<GenericSignatureBuilder> replacementBuilder;
+    if (!source->parent->parent && requirementSignatureProto) {
+      // If we have a requirement signature now, we're done.
+      if (source->usesRequirementSignature) {
+        Type subjectType = source->getStoredType()->getCanonicalType();
+        path.push_back({subjectType, conformingProto});
+        return;
+      }
+
+      // The generic signature builder we're using for this protocol
+      // wasn't built from its own requirement signature, so we can't
+      // trust it. Make sure we have a requirement signature, then build
+      // a new generic signature builder.
+      // FIXME: It would be better if we could replace the canonical generic
+      // signature builder with the rebuilt one.
+      if (!requirementSignatureProto->isRequirementSignatureComputed())
+        requirementSignatureProto->computeRequirementSignature();
+      assert(requirementSignatureProto->isRequirementSignatureComputed());
+
+      replacementBuilder.emplace(getASTContext());
+      replacementBuilder->addGenericSignature(
+                          requirementSignatureProto->getGenericSignature());
+      replacementBuilder->processDelayedRequirements();
+    }
+
+    // Follow the rest of the path to derive the conformance into which
+    // this particular protocol requirement step would look.
+    auto inProtocol = source->getProtocolDecl();
+    buildConformanceAccessPath(path, reqs, source->parent, inProtocol, rootType,
+                               requirementSignatureProto);
+    assert(path.back().second == inProtocol &&
+           "path produces incorrect conformance");
+
+    // If this step was computed via the requirement signature, add it
+    // directly.
+    if (source->usesRequirementSignature) {
+      // Add this step along the path, which involves looking for the
+      // conformance we want (\c conformingProto) within the protocol
+      // described by this source.
+
+      // Canonicalize the subject type within the protocol's generic
+      // signature.
+      Type subjectType = source->getStoredType();
+      subjectType = inProtocol->getGenericSignature()
+        ->getCanonicalTypeInContext(subjectType);
+
+      assert(hasConformanceInSignature(inProtocol->getRequirementSignature(),
+                                       subjectType, conformingProto) &&
+             "missing explicit conformance in requirement signature");
+
+      // Record this step.
+      path.push_back({subjectType, conformingProto});
+      return;
+    }
+
+    // Get the generic signature builder for the protocol.
+    // Get a generic signature for the protocol's signature.
+    auto inProtoSig = inProtocol->getGenericSignature();
+    auto &inProtoSigBuilder =
+        replacementBuilder ? *replacementBuilder
+                           : *inProtoSig->getGenericSignatureBuilder();
+
+    // Retrieve the stored type, but erase all of the specific associated
+    // type declarations; we don't want any details of the enclosing context
+    // to sneak in here.
+    Type storedType = eraseAssociatedTypes(source->getStoredType());
+
+    // Dig out the potential archetype for this stored type.
+    auto equivClass =
+      inProtoSigBuilder.resolveEquivalenceClass(
+                               storedType,
+                               ArchetypeResolutionKind::CompleteWellFormed);
+
+    // Find the conformance of this potential archetype to the protocol in
+    // question.
+    auto conforms = equivClass->conformsTo.find(conformingProto);
+    assert(conforms != equivClass->conformsTo.end());
+
+    // Compute the root type, canonicalizing it w.r.t. the protocol context.
+    auto conformsSource = getBestRequirementSource(conforms->second);
+    assert(conformsSource != source || !requirementSignatureProto);
+    Type localRootType = conformsSource->getRootType();
+    localRootType = inProtoSig->getCanonicalTypeInContext(localRootType);
+
+    // Build the path according to the requirement signature.
+    buildConformanceAccessPath(path, inProtocol->getRequirementSignature(),
+                               conformsSource, conformingProto, localRootType,
+                               inProtocol);
+
+    // We're done.
+    return;
+  }
+
+  // If we have a superclass or concrete requirement, the conformance
+  // we need is stored in it.
+  if (source->kind == RequirementSource::Superclass ||
+      source->kind == RequirementSource::Concrete) {
+    auto conformance = source->getProtocolConformance();
+    (void)conformance;
+    assert(conformance.getRequirement() == conformingProto);
+    path.push_back({source->getAffectedType(), conformingProto});
+    return;
+  }
+
+  // If we still have a parent, keep going.
+  if (source->parent) {
+    buildConformanceAccessPath(path, reqs, source->parent, conformingProto,
+                               rootType, requirementSignatureProto);
+    return;
+  }
+
+  // We are at an explicit or inferred requirement.
+  assert(source->kind == RequirementSource::Explicit ||
+         source->kind == RequirementSource::Inferred);
+
+  // Skip trivial path elements. These occur when querying a requirement
+  // signature.
+  if (!path.empty() && conformingProto == path.back().second &&
+      rootType->isEqual(conformingProto->getSelfInterfaceType()))
+    return;
+
+  assert(hasConformanceInSignature(reqs, rootType, conformingProto) &&
+         "missing explicit conformance in signature");
+
+  // Add the root of the path, which starts at this explicit requirement.
+  path.push_back({rootType, conformingProto});
+}
+
+ConformanceAccessPath
+GenericSignature::getConformanceAccessPath(Type type, ProtocolDecl *protocol) {
   assert(type->isTypeParameter() && "not a type parameter");
 
   // Resolve this type to a potential archetype.
@@ -829,163 +967,28 @@
                                   type,
                                   ArchetypeResolutionKind::CompleteWellFormed);
 
+  auto cached = equivClass->conformanceAccessPathCache.find(protocol);
+  if (cached != equivClass->conformanceAccessPathCache.end())
+    return cached->second;
+
   // Dig out the conformance of this type to the given protocol, because we
   // want its requirement source.
   auto conforms = equivClass->conformsTo.find(protocol);
   assert(conforms != equivClass->conformsTo.end());
 
-  // Follow the requirement source to form the conformance access path.
-  typedef GenericSignatureBuilder::RequirementSource RequirementSource;
-  ConformanceAccessPath path;
-
-  // Local function to construct the conformance access path from the
-  // requirement.
-  std::function<void(ArrayRef<Requirement>, const RequirementSource *,
-                     ProtocolDecl *, Type, ProtocolDecl *)> buildPath;
-  buildPath = [&](ArrayRef<Requirement> reqs, const RequirementSource *source,
-                  ProtocolDecl *conformingProto, Type rootType,
-                  ProtocolDecl *requirementSignatureProto) {
-    // Each protocol requirement is a step along the path.
-    if (source->isProtocolRequirement()) {
-      // If we're expanding for a protocol that had no requirement signature
-      // and have hit the penultimate step, this is the last step
-      // that would occur in the requirement signature.
-      Optional<GenericSignatureBuilder> replacementBuilder;
-      if (!source->parent->parent && requirementSignatureProto) {
-        // If we have a requirement signature now, we're done.
-        if (source->usesRequirementSignature) {
-          Type subjectType = source->getStoredType()->getCanonicalType();
-          path.path.push_back({subjectType, conformingProto});
-          return;
-        }
-
-        // The generic signature builder we're using for this protocol
-        // wasn't built from its own requirement signature, so we can't
-        // trust it. Make sure we have a requirement signature, then build
-        // a new generic signature builder.
-        // FIXME: It would be better if we could replace the canonical generic
-        // signature builder with the rebuilt one.
-        if (!requirementSignatureProto->isRequirementSignatureComputed())
-          requirementSignatureProto->computeRequirementSignature();
-        assert(requirementSignatureProto->isRequirementSignatureComputed());
-
-        replacementBuilder.emplace(getASTContext());
-        replacementBuilder->addGenericSignature(
-                            requirementSignatureProto->getGenericSignature());
-        replacementBuilder->processDelayedRequirements();
-      }
-
-      // Follow the rest of the path to derive the conformance into which
-      // this particular protocol requirement step would look.
-      auto inProtocol = source->getProtocolDecl();
-      buildPath(reqs, source->parent, inProtocol, rootType,
-                requirementSignatureProto);
-      assert(path.path.back().second == inProtocol &&
-             "path produces incorrect conformance");
-
-      // If this step was computed via the requirement signature, add it
-      // directly.
-      if (source->usesRequirementSignature) {
-        // Add this step along the path, which involves looking for the
-        // conformance we want (\c conformingProto) within the protocol
-        // described by this source.
-
-        // Canonicalize the subject type within the protocol's generic
-        // signature.
-        Type subjectType = source->getStoredType();
-        subjectType = inProtocol->getGenericSignature()
-          ->getCanonicalTypeInContext(subjectType);
-
-        assert(hasConformanceInSignature(inProtocol->getRequirementSignature(),
-                                         subjectType, conformingProto) &&
-               "missing explicit conformance in requirement signature");
-
-        // Record this step.
-        path.path.push_back({subjectType, conformingProto});
-        return;
-      }
-
-      // Get the generic signature builder for the protocol.
-      // Get a generic signature for the protocol's signature.
-      auto inProtoSig = inProtocol->getGenericSignature();
-      auto &inProtoSigBuilder =
-          replacementBuilder ? *replacementBuilder
-                             : *inProtoSig->getGenericSignatureBuilder();
-
-      // Retrieve the stored type, but erase all of the specific associated
-      // type declarations; we don't want any details of the enclosing context
-      // to sneak in here.
-      Type storedType = eraseAssociatedTypes(source->getStoredType());
-
-      // Dig out the potential archetype for this stored type.
-      auto equivClass =
-        inProtoSigBuilder.resolveEquivalenceClass(
-                                 storedType,
-                                 ArchetypeResolutionKind::CompleteWellFormed);
-
-      // Find the conformance of this potential archetype to the protocol in
-      // question.
-      auto conforms = equivClass->conformsTo.find(conformingProto);
-      assert(conforms != equivClass->conformsTo.end());
-
-      // Compute the root type, canonicalizing it w.r.t. the protocol context.
-      auto conformsSource = getBestRequirementSource(conforms->second);
-      assert(conformsSource != source || !requirementSignatureProto);
-      Type localRootType = conformsSource->getRootType();
-      localRootType = inProtoSig->getCanonicalTypeInContext(localRootType);
-
-      // Build the path according to the requirement signature.
-      buildPath(inProtocol->getRequirementSignature(), conformsSource,
-                conformingProto, localRootType, inProtocol);
-
-      // We're done.
-      return;
-    }
-
-    // If we have a superclass or concrete requirement, the conformance
-    // we need is stored in it.
-    if (source->kind == RequirementSource::Superclass ||
-        source->kind == RequirementSource::Concrete) {
-      auto conformance = source->getProtocolConformance();
-      (void)conformance;
-      assert(conformance.getRequirement() == conformingProto);
-      path.path.push_back({source->getAffectedType(), conformingProto});
-      return;
-    }
-
-    // If we still have a parent, keep going.
-    if (source->parent) {
-      buildPath(reqs, source->parent, conformingProto, rootType,
-                requirementSignatureProto);
-      return;
-    }
-
-    // We are at an explicit or inferred requirement.
-    assert(source->kind == RequirementSource::Explicit ||
-           source->kind == RequirementSource::Inferred);
-
-    // Skip trivial path elements. These occur when querying a requirement
-    // signature.
-    if (!path.path.empty() && conformingProto == path.path.back().second &&
-        rootType->isEqual(conformingProto->getSelfInterfaceType()))
-      return;
-
-    assert(hasConformanceInSignature(reqs, rootType, conformingProto) &&
-           "missing explicit conformance in signature");
-
-    // Add the root of the path, which starts at this explicit requirement.
-    path.path.push_back({rootType, conformingProto});
-  };
-
   // Canonicalize the root type.
   auto source = getBestRequirementSource(conforms->second);
   Type rootType = source->getRootType()->getCanonicalType(this);
 
   // Build the path.
-  buildPath(getRequirements(), source, protocol, rootType, nullptr);
+  SmallVector<ConformanceAccessPath::Entry, 2> path;
+  buildConformanceAccessPath(path, getRequirements(), source, protocol,
+                             rootType, nullptr);
 
   // Return the path; we're done!
-  return path;
+  ConformanceAccessPath result(getASTContext().AllocateCopy(path));
+  equivClass->conformanceAccessPathCache.insert({protocol, result});
+  return result;
 }
 
 unsigned GenericParamKey::findIndexIn(
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index c9a78be..e3c7b0d 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -983,18 +983,28 @@
   
   if (auto nom = type->getAnyNominal()) {
     // TODO: Generic metadata patterns relative-reference their VWT, which won't
-    // work if it's in a different module without supporting indirection through
-    // the GOT.
+    // work if the VWT is in a different module without supporting indirection
+    // through the GOT.
     if (nom->isGenericContext())
       return nullptr;
-    // TODO: Enums need additional value witnesses for their tag manipulation.
-    if (isa<EnumDecl>(nom))
-      return nullptr;
+    // TODO: Non-C enums have extra inhabitants and also need additional value
+    // witnesses for their tag manipulation (except when they're empty, in
+    // which case values never exist to witness).
+    if (auto enumDecl = dyn_cast<EnumDecl>(nom))
+      if (!enumDecl->isObjC() && !type->isUninhabited())
+        return nullptr;
   }
-  
+ 
+  auto &C = IGM.Context;
+
   type = getFormalTypeInContext(type);
   
   auto &ti = IGM.getTypeInfoForUnlowered(AbstractionPattern::getOpaque(), type);
+
+  // Empty types can use empty tuple witnesses.
+  if (ti.isKnownEmpty(ResilienceExpansion::Maximal))
+    return IGM.getAddrOfValueWitnessTable(TupleType::getEmpty(C));
+
   // We only have witnesses for fixed type info.
   auto *fixedTI = dyn_cast<FixedTypeInfo>(&ti);
   if (!fixedTI)
@@ -1003,7 +1013,6 @@
   CanType witnessSurrogate;
 
   // Handle common POD type layouts.
-  auto &C = type->getASTContext();
   ReferenceCounting refCounting;
   if (fixedTI->isPOD(ResilienceExpansion::Maximal)
       && fixedTI->getFixedExtraInhabitantCount(IGM) == 0) {
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 963dc00..e4e80c9 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -2609,7 +2609,8 @@
     case SILInstructionKind::ConvertFunctionInst: {
       auto instr = cast<ConvertFunctionInst>(convInstr);
       newInstr = convBuilder.createConvertFunction(
-          instr->getLoc(), instr->getOperand(), newType);
+          instr->getLoc(), instr->getOperand(), newType,
+          instr->withoutActuallyEscaping());
       break;
     }
     case SILInstructionKind::ConvertEscapeToNoEscapeInst: {
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 82e0341..b43573f 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -2182,7 +2182,8 @@
       size_t BOMLen = ContentStart - BufferStart;
       assert(BOMLen == 3 && "UTF-8 BOM is 3 bytes");
       // Add UTF-8 BOM to LeadingTrivia.
-      LeadingTrivia.push_back(TriviaPiece::garbageText({CurPtr, BOMLen}));
+      auto Text = OwnedString::makeRefCounted(StringRef(CurPtr, BOMLen));
+      LeadingTrivia.push_back(TriviaPiece::garbageText(Text));
       CurPtr += BOMLen;
     }
     NextToken.setAtStartOfLine(true);
@@ -2407,18 +2408,18 @@
       bool isDocComment = CurPtr[1] == '/';
       skipSlashSlashComment(/*EatNewline=*/false);
       size_t Length = CurPtr - TriviaStart;
-      Pieces.push_back(isDocComment
-                           ? TriviaPiece::docLineComment({TriviaStart, Length})
-                           : TriviaPiece::lineComment({TriviaStart, Length}));
+      auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+      Pieces.push_back(isDocComment ? TriviaPiece::docLineComment(Text)
+                                    : TriviaPiece::lineComment(Text));
       goto Restart;
     } else if (*CurPtr == '*') {
       // '/* ... */' comment.
       bool isDocComment = CurPtr[1] == '*';
       skipSlashStarComment();
       size_t Length = CurPtr - TriviaStart;
-      Pieces.push_back(isDocComment
-                           ? TriviaPiece::docBlockComment({TriviaStart, Length})
-                           : TriviaPiece::blockComment({TriviaStart, Length}));
+      auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+      Pieces.push_back(isDocComment ? TriviaPiece::docBlockComment(Text)
+                                    : TriviaPiece::blockComment(Text));
       goto Restart;
     }
     break;
@@ -2430,7 +2431,8 @@
         diagnose(TriviaStart, diag::lex_hashbang_not_allowed);
       skipHashbang(/*EatNewline=*/false);
       size_t Length = CurPtr - TriviaStart;
-      Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+      auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+      Pieces.push_back(TriviaPiece::garbageText(Text));
       goto Restart;
     }
     break;
@@ -2439,7 +2441,8 @@
     if (tryLexConflictMarker(/*EatNewline=*/false)) {
       // Conflict marker.
       size_t Length = CurPtr - TriviaStart;
-      Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+      auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+      Pieces.push_back(TriviaPiece::garbageText(Text));
       goto Restart;
     }
     break;
@@ -2448,7 +2451,8 @@
     case NulCharacterKind::Embedded: {
       diagnoseEmbeddedNul(Diags, CurPtr - 1);
       size_t Length = CurPtr - TriviaStart;
-      Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+      auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+      Pieces.push_back(TriviaPiece::garbageText(Text));
       goto Restart;
     }
     case NulCharacterKind::CodeCompletion:
@@ -2494,7 +2498,8 @@
     }
 
     size_t Length = CurPtr - TriviaStart;
-    Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+    auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
+    Pieces.push_back(TriviaPiece::garbageText(Text));
     goto Restart;
   }
   // Reset the cursor.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index dfdd6e0..65b762de 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -312,15 +312,15 @@
   syntax::AbsolutePosition RunningPos;
 
   tokenize(
-      LangOpts, SM, BufferID, Offset, EndOffset,
-      Diags,
+      LangOpts, SM, BufferID, Offset, EndOffset, Diags,
       CommentRetentionMode::AttachToNextToken, TriviaRetentionMode::WithTrivia,
       /*TokenizeInterpolatedString=*/false,
       /*SplitTokens=*/ArrayRef<Token>(),
       [&](const Token &Tok, const Trivia &LeadingTrivia,
           const Trivia &TrailingTrivia) {
+        auto Text = OwnedString::makeRefCounted(Tok.getText());
         auto ThisToken =
-            RawSyntax::make(Tok.getKind(), Tok.getText(), LeadingTrivia.Pieces,
+            RawSyntax::make(Tok.getKind(), Text, LeadingTrivia.Pieces,
                             TrailingTrivia.Pieces, SourcePresence::Present);
 
         auto ThisTokenPos = ThisToken->accumulateAbsolutePosition(RunningPos);
@@ -1016,6 +1016,13 @@
             Opts.CollectParsedToken,
             Opts.BuildSyntaxTree)) {
   }
+
+  ~Implementation() {
+    // We need to delete the parser before the context so that it can finalize
+    // its SourceFileSyntax while it is still alive
+    TheParser.reset();
+    delete &Ctx;
+  }
 };
 
 ParserUnit::ParserUnit(SourceManager &SM, unsigned BufferID)
diff --git a/lib/Parse/SyntaxParsingContext.cpp b/lib/Parse/SyntaxParsingContext.cpp
index 8a5214e..34c8c5b 100644
--- a/lib/Parse/SyntaxParsingContext.cpp
+++ b/lib/Parse/SyntaxParsingContext.cpp
@@ -163,9 +163,9 @@
     return;
 
   auto &Arena = getArena();
-  addRawSyntax(RawSyntax::getToken(Arena, Tok.getKind(), Tok.getText(),
-                                   LeadingTrivia.Pieces,
-                                   TrailingTrivia.Pieces));
+  auto Text = OwnedString::makeRefCounted(Tok.getText());
+  addRawSyntax(RawSyntax::getToken(
+      Arena, Tok.getKind(), Text, LeadingTrivia.Pieces, TrailingTrivia.Pieces));
 }
 
 /// Add Syntax to the parts.
@@ -313,7 +313,7 @@
   }
 
   if (!EOFToken)
-    EOFToken = RawSyntax::missing(tok::eof, "");
+    EOFToken = RawSyntax::missing(tok::eof, OwnedString::makeUnowned(""));
 
   auto newRaw = SyntaxFactory::createRaw(
       SyntaxKind::SourceFile,
@@ -352,7 +352,8 @@
     return;
   if (Text.empty())
     Text = getTokenText(Kind);
-  getStorage().push_back(RawSyntax::missing(Kind, Text));
+  auto OwnedText = OwnedString::makeRefCounted(Text);
+  getStorage().push_back(RawSyntax::missing(Kind, OwnedText));
 }
 
 void SyntaxParsingContext::synthesize(SyntaxKind Kind) {
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 5167087..81745a9 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -886,6 +886,7 @@
                                  Inline_t *inlineStrategy,
                                  OptimizationMode *optimizationMode,
                                  bool *isLet, bool *isWeakLinked,
+                                 bool *isWithoutActuallyEscapingThunk,
                                  SmallVectorImpl<std::string> *Semantics,
                                  SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
                                  ValueDecl **ClangDecl,
@@ -914,6 +915,9 @@
       *isThunk = IsSignatureOptimizedThunk;
     else if (isThunk && SP.P.Tok.getText() == "reabstraction_thunk")
       *isThunk = IsReabstractionThunk;
+    else if (isWithoutActuallyEscapingThunk
+             && SP.P.Tok.getText() == "without_actually_escaping")
+      *isWithoutActuallyEscapingThunk = true;
     else if (isGlobalInit && SP.P.Tok.getText() == "global_init")
       *isGlobalInit = true;
     else if (isWeakLinked && SP.P.Tok.getText() == "_weakLinked")
@@ -2976,6 +2980,7 @@
     SourceLoc ToLoc;
     bool not_guaranteed = false;
     bool escaped = false;
+    bool without_actually_escaping = false;
     if (Opcode == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
       StringRef attrName;
       if (parseSILOptional(attrName, *this)) {
@@ -2989,17 +2994,26 @@
       if (parseSILOptional(escaped, *this, "escaped"))
         return true;
     }
-    if (parseTypedValueRef(Val, B) ||
-        parseSILIdentifier(ToToken, ToLoc,
-                           diag::expected_tok_in_sil_instr, "to") ||
-        parseSILType(Ty) ||
-        parseSILDebugLocation(InstLoc, B))
+    if (parseTypedValueRef(Val, B)
+        || parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
+                              "to"))
       return true;
 
     if (ToToken.str() != "to") {
       P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
       return true;
     }
+    if (Opcode == SILInstructionKind::ConvertFunctionInst) {
+      StringRef attrName;
+      if (parseSILOptional(attrName, *this)) {
+        if (attrName.equals("without_actually_escaping"))
+          without_actually_escaping = true;
+        else
+          return true;
+      }
+    }
+    if (parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
+      return true;
 
     switch (Opcode) {
     default: llvm_unreachable("Out of sync with parent switch");
@@ -3019,7 +3033,8 @@
       ResultVal = B.createUpcast(InstLoc, Val, Ty);
       break;
     case SILInstructionKind::ConvertFunctionInst:
-      ResultVal = B.createConvertFunction(InstLoc, Val, Ty);
+      ResultVal =
+          B.createConvertFunction(InstLoc, Val, Ty, without_actually_escaping);
       break;
     case SILInstructionKind::ConvertEscapeToNoEscapeInst:
       ResultVal = B.createConvertEscapeToNoEscape(InstLoc, Val, Ty, escaped,
@@ -5186,6 +5201,7 @@
   bool isCanonical = false;
   IsThunk_t isThunk = IsNotThunk;
   bool isGlobalInit = false, isWeakLinked = false;
+  bool isWithoutActuallyEscapingThunk = false;
   Inline_t inlineStrategy = InlineDefault;
   OptimizationMode optimizationMode = OptimizationMode::NotSet;
   SmallVector<std::string, 1> Semantics;
@@ -5196,7 +5212,8 @@
       parseDeclSILOptional(&isTransparent, &isSerialized, &isCanonical,
                            &isThunk, &isGlobalInit,
                            &inlineStrategy, &optimizationMode, nullptr,
-                           &isWeakLinked, &Semantics, &SpecAttrs,
+                           &isWeakLinked, &isWithoutActuallyEscapingThunk,
+                           &Semantics, &SpecAttrs,
                            &ClangDecl, &MRK, FunctionState) ||
       P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
       P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -5224,6 +5241,8 @@
     FunctionState.F->setThunk(IsThunk_t(isThunk));
     FunctionState.F->setGlobalInit(isGlobalInit);
     FunctionState.F->setWeakLinked(isWeakLinked);
+    FunctionState.F->setWithoutActuallyEscapingThunk(
+      isWithoutActuallyEscapingThunk);
     FunctionState.F->setInlineStrategy(inlineStrategy);
     FunctionState.F->setOptimizationMode(optimizationMode);
     FunctionState.F->setEffectsKind(MRK);
@@ -5403,7 +5422,7 @@
   if (parseSILLinkage(GlobalLinkage, P) ||
       parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
                            nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
-                           nullptr, nullptr, State) ||
+                           nullptr, nullptr, nullptr, State) ||
       P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
       P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
       P.parseToken(tok::colon, diag::expected_sil_type))
@@ -5451,7 +5470,7 @@
   IsSerialized_t Serialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
                            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-                           nullptr, nullptr, SP))
+                           nullptr, nullptr, nullptr, SP))
     return true;
   
   ValueDecl *VD;
@@ -5519,7 +5538,7 @@
   IsSerialized_t Serialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
                            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-                           nullptr, nullptr, VTableState))
+                           nullptr, nullptr, nullptr, VTableState))
     return true;
 
   // Parse the class name.
@@ -5869,7 +5888,7 @@
   IsSerialized_t isSerialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
                            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-                           nullptr, nullptr, WitnessState))
+                           nullptr, nullptr, nullptr, WitnessState))
     return true;
 
   Scope S(&P, ScopeKind::TopLevel);
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 988670a..760d59a 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -1971,10 +1971,9 @@
                                                   TypeDependentOperands, Ty);
 }
 
-ConvertFunctionInst *
-ConvertFunctionInst::create(SILDebugLocation DebugLoc, SILValue Operand,
-                            SILType Ty, SILFunction &F,
-                            SILOpenedArchetypesState &OpenedArchetypes) {
+ConvertFunctionInst *ConvertFunctionInst::create(
+    SILDebugLocation DebugLoc, SILValue Operand, SILType Ty, SILFunction &F,
+    SILOpenedArchetypesState &OpenedArchetypes, bool WithoutActuallyEscaping) {
   SILModule &Mod = F.getModule();
   SmallVector<SILValue, 8> TypeDependentOperands;
   collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
@@ -1982,8 +1981,8 @@
   unsigned size =
     totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
   void *Buffer = Mod.allocateInst(size, alignof(ConvertFunctionInst));
-  auto *CFI = ::new (Buffer)
-      ConvertFunctionInst(DebugLoc, Operand, TypeDependentOperands, Ty);
+  auto *CFI = ::new (Buffer) ConvertFunctionInst(
+      DebugLoc, Operand, TypeDependentOperands, Ty, WithoutActuallyEscaping);
   // If we do not have lowered SIL, make sure that are not performing
   // ABI-incompatible conversions.
   //
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index a6a973d..b87ca29 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1424,7 +1424,10 @@
   }
 
   void visitConvertFunctionInst(ConvertFunctionInst *CI) {
-    printUncheckedConversionInst(CI, CI->getOperand());
+    *this << getIDAndType(CI->getOperand()) << " to ";
+    if (CI->withoutActuallyEscaping())
+      *this << "[without_actually_escaping] ";
+    *this << CI->getType();
   }
   void visitConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *CI) {
     *this << (CI->isLifetimeGuaranteed() ? "" : "[not_guaranteed] ")
@@ -2299,6 +2302,8 @@
     break;
   case IsReabstractionThunk: OS << "[reabstraction_thunk] "; break;
   }
+  if (isWithoutActuallyEscapingThunk())
+    OS << "[without_actually_escaping] ";
 
   if (isGlobalInit())
     OS << "[global_init] ";
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index 294cb17..35f3ff7 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -207,12 +207,13 @@
   return getSILGenFunction().emitManagedRValueWithCleanup(result);
 }
 
-ManagedValue SILGenBuilder::createConvertFunction(SILLocation loc,
-                                                  ManagedValue fn,
-                                                  SILType resultTy) {
+ManagedValue
+SILGenBuilder::createConvertFunction(SILLocation loc, ManagedValue fn,
+                                     SILType resultTy,
+                                     bool withoutActuallyEscaping) {
   CleanupCloner cloner(*this, fn);
-  SILValue result =
-      createConvertFunction(loc, fn.forward(getSILGenFunction()), resultTy);
+  SILValue result = SILBuilder::createConvertFunction(
+      loc, fn.forward(getSILGenFunction()), resultTy, withoutActuallyEscaping);
   return cloner.clone(result);
 }
 
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index b62e64d..5530833 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -365,7 +365,8 @@
 
   using SILBuilder::createConvertFunction;
   ManagedValue createConvertFunction(SILLocation loc, ManagedValue fn,
-                                     SILType resultTy);
+                                     SILType resultTy,
+                                     bool WithoutActuallyEscaping = false);
 
   using SILBuilder::createConvertEscapeToNoEscape;
   ManagedValue
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index d8507e1..f125508 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1703,9 +1703,8 @@
     assert(result.getType() == loweredResultTy);
 
     if (loweredResultTy != loweredDestTy) {
-      result = ManagedValue::forUnmanaged(
-          SGF.B.createConvertFunction(e, result.getUnmanagedValue(),
-                                      loweredDestTy));
+      assert(!result.hasCleanup());
+      result = SGF.B.createConvertFunction(e, result, loweredDestTy);
     }
 
     break;
@@ -1958,9 +1957,9 @@
   CanAnyFunctionType destTy
     = cast<AnyFunctionType>(e->getType()->getCanonicalType());
   SILType resultType = SGF.getLoweredType(destTy);
-  SILValue result = SGF.B.createConvertFunction(e, 
-                                                original.forward(SGF),
-                                                resultType);
+  SILValue result =
+      SGF.B.createConvertFunction(e, original.forward(SGF), resultType,
+                                  /*Withoutactuallyescaping=*/false);
   return RValue(SGF, e, SGF.emitManagedRValueWithCleanup(result));
 }
 
@@ -5279,7 +5278,8 @@
   if (silFnTy->getExtInfo().getRepresentation() !=
       SILFunctionTypeRepresentation::Thick) {
     auto escapingClosure =
-        SGF.B.createConvertFunction(E, functionValue, escapingFnTy);
+        SGF.B.createConvertFunction(E, functionValue, escapingFnTy,
+                                    /*WithoutActuallyEscaping=*/true);
     return visitSubExpr(escapingClosure, true /*isClosureConsumable*/);
   }
 
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index e885b2e..48ae9fc 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -3017,10 +3017,12 @@
       thunkType, noEscapingFnTy, escapingFnTy, F.isSerialized());
 
   if (thunk->empty()) {
+    thunk->setWithoutActuallyEscapingThunk();
     thunk->setGenericEnvironment(genericEnv);
     SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
     buildWithoutActuallyEscapingThunkBody(thunkSGF);
   }
+  assert(thunk->isWithoutActuallyEscapingThunk());
 
   CanSILFunctionType substFnTy = thunkType;
   // Use the subsitution map in the context of the current function.
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 54bd1d2..bce8321 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -670,7 +670,8 @@
     calleeValue = cloneCalleeConversion(CFI->getOperand(), NewClosure, Builder,
                                         NeedsRelease);
     return Builder.createConvertFunction(CallSiteDesc.getLoc(), calleeValue,
-                                         CFI->getType());
+                                         CFI->getType(),
+                                         CFI->withoutActuallyEscaping());
   }
 
   if (auto *PAI = dyn_cast<PartialApplyInst>(calleeValue)) {
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index e28a724..a27d611 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -967,12 +967,24 @@
   if (isIncidentalUse(user) || onlyAffectsRefCount(user))
     return;
 
+  // Before checking conversions in general below (getSingleValueCopyOrCast),
+  // check for convert_function to [without_actually_escaping]. Assume such
+  // conversion are not actually escaping without following their uses.
+  if (auto *CFI = dyn_cast<ConvertFunctionInst>(user)) {
+    if (CFI->withoutActuallyEscaping())
+      return;
+  }
+
   // Look through copies, borrows, and conversions.
   //
   // Note: This handles ConversionInst, which already includes everything in
   // swift::stripConvertFunctions.
   if (SingleValueInstruction *copy = getSingleValueCopyOrCast(user)) {
-    followUses(copy);
+    // Only follow the copied operand. Other operands are incidental,
+    // as in the second operand of mark_dependence.
+    if (oper->getOperandNumber() == 0)
+      followUses(copy);
+
     return;
   }
 
@@ -1017,6 +1029,10 @@
     }
     break;
 
+  case SILInstructionKind::IsEscapingClosureInst:
+    // May be generated by withoutActuallyEscaping.
+    return;
+
   case SILInstructionKind::PartialApplyInst: {
     // Recurse through partial_apply to handle special cases before handling
     // ApplySites in general below.
@@ -1036,7 +1052,10 @@
     // thunk as "escaping", but as long as the thunk is only used as a
     // '@noescape" type then it is safe.
     if (isPartialApplyOfReabstractionThunk(PAI)) {
-      followUses(PAI);
+      // Don't follow thunks that were generated by withoutActuallyEscaping.
+      SILFunction *thunkDef = PAI->getReferencedFunction();
+      if (!thunkDef->isWithoutActuallyEscapingThunk())
+        followUses(PAI);
       return;
     }
     // Handle this use like a normal applied argument.
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 17fe8f3..2c2ffb4 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -585,7 +585,8 @@
                  "Swift thick functions that differ in escapeness are not ABI "
                  "compatible");
       // Insert convert_function.
-      return B->createConvertFunction(Loc, Value, DestTy);
+      return B->createConvertFunction(Loc, Value, DestTy,
+                                      /*WithoutActuallyEscaping=*/false);
     }
   }
 
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index f3d1d93..980a6b1 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -463,15 +463,16 @@
   DeclID clangNodeOwnerID;
   TypeID funcTyID;
   GenericEnvironmentID genericEnvID;
-  unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
-      inlineStrategy, optimizationMode, effect, numSpecAttrs,
-      hasQualifiedOwnership, isWeakLinked;
+  unsigned rawLinkage, isTransparent, isSerialized, isThunk,
+      isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
+      optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
+      isWeakLinked;
   ArrayRef<uint64_t> SemanticsIDs;
-  SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
-                                isThunk, isGlobal, inlineStrategy,
-                                optimizationMode, effect, numSpecAttrs,
-                                hasQualifiedOwnership, isWeakLinked, funcTyID,
-                                genericEnvID, clangNodeOwnerID, SemanticsIDs);
+  SILFunctionLayout::readRecord(
+      scratch, rawLinkage, isTransparent, isSerialized, isThunk,
+      isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
+      optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
+      isWeakLinked, funcTyID, genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
   if (funcTyID == 0) {
     LLVM_DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n");
@@ -556,6 +557,7 @@
     fn->setTransparent(IsTransparent_t(isTransparent == 1));
     fn->setSerialized(IsSerialized_t(isSerialized));
     fn->setThunk(IsThunk_t(isThunk));
+    fn->setWithoutActuallyEscapingThunk(bool(isWithoutactuallyEscapingThunk));
     fn->setInlineStrategy(Inline_t(inlineStrategy));
     fn->setGlobalInit(isGlobal == 1);
     fn->setEffectsKind(EffectsKind(effect));
@@ -1132,7 +1134,6 @@
   ONEOPERAND_ONETYPE_INST(ObjCToThickMetatype)
   ONEOPERAND_ONETYPE_INST(ObjCMetatypeToObject)
   ONEOPERAND_ONETYPE_INST(ObjCExistentialMetatypeToObject)
-  ONEOPERAND_ONETYPE_INST(ConvertFunction)
   ONEOPERAND_ONETYPE_INST(ThinFunctionToPointer)
   ONEOPERAND_ONETYPE_INST(PointerToThinFunction)
   ONEOPERAND_ONETYPE_INST(ProjectBlockStorage)
@@ -1161,7 +1162,18 @@
         isLifetimeGuaranteed);
     break;
   }
-
+  case SILInstructionKind::ConvertFunctionInst: {
+    assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND
+           && "Layout should be OneTypeOneOperand.");
+    bool withoutActuallyEscaping = Attr & 0x01;
+    ResultVal = Builder.createConvertFunction(
+        Loc,
+        getLocalValue(ValID, getSILType(MF->getType(TyID2),
+                                        (SILValueCategory)TyCategory2)),
+        getSILType(MF->getType(TyID), (SILValueCategory)TyCategory),
+        withoutActuallyEscaping);
+    break;
+  }
   case SILInstructionKind::PointerToAddressInst: {
     assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
            "Layout should be OneTypeOneOperand.");
@@ -2480,15 +2492,16 @@
   DeclID clangOwnerID;
   TypeID funcTyID;
   GenericEnvironmentID genericEnvID;
-  unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
-    inlineStrategy, optimizationMode, effect, numSpecAttrs,
-    hasQualifiedOwnership, isWeakLinked;
+  unsigned rawLinkage, isTransparent, isSerialized, isThunk,
+      isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
+      optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
+      isWeakLinked;
   ArrayRef<uint64_t> SemanticsIDs;
-  SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
-                                isThunk, isGlobal, inlineStrategy,
-                                optimizationMode, effect, numSpecAttrs,
-                                hasQualifiedOwnership, isWeakLinked, funcTyID,
-                                genericEnvID, clangOwnerID, SemanticsIDs);
+  SILFunctionLayout::readRecord(
+      scratch, rawLinkage, isTransparent, isSerialized, isThunk,
+      isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
+      optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
+      isWeakLinked, funcTyID, genericEnvID, clangOwnerID, SemanticsIDs);
   auto linkage = fromStableSILLinkage(rawLinkage);
   if (!linkage) {
     LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index fcec9e8..0375fca 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -288,6 +288,7 @@
                      BCFixed<1>,  // transparent
                      BCFixed<2>,  // serialized
                      BCFixed<2>,  // thunks: signature optimized/reabstraction
+                     BCFixed<1>,  // without_actually_escaping
                      BCFixed<1>,  // global_init
                      BCFixed<2>,  // inlineStrategy
                      BCFixed<2>,  // optimizationMode
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 9bb3055..60c48bc 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -242,7 +242,7 @@
     void writeIndexTables();
 
     void writeConversionLikeInstruction(const SingleValueInstruction *I,
-                                        bool guaranteed, bool escaped);
+                                        unsigned attrs);
     void writeOneTypeLayout(SILInstructionKind valueKind, SILType type);
     void writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
                                       unsigned attrs,
@@ -399,9 +399,9 @@
   SILFunctionLayout::emitRecord(
       Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage),
       (unsigned)F.isTransparent(), (unsigned)F.isSerialized(),
-      (unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
-      (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
-      (unsigned)F.getEffectsKind(),
+      (unsigned)F.isThunk(), (unsigned)F.isWithoutActuallyEscapingThunk(),
+      (unsigned)F.isGlobalInit(), (unsigned)F.getInlineStrategy(),
+      (unsigned)F.getOptimizationMode(), (unsigned)F.getEffectsKind(),
       (unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(),
       F.isWeakLinked(), FnID, genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
@@ -591,11 +591,10 @@
 /// Write an instruction that looks exactly like a conversion: all
 /// important information is encoded in the operand and the result type.
 void SILSerializer::writeConversionLikeInstruction(
-    const SingleValueInstruction *I, bool guaranteed, bool escaped) {
+    const SingleValueInstruction *I, unsigned attrs) {
   assert(I->getNumOperands() - I->getTypeDependentOperands().size() == 1);
-  writeOneTypeOneOperandLayout(I->getKind(),
-                               (guaranteed ? 1 : 0) | (escaped ? 2 : 0),
-                               I->getType(), I->getOperand(0));
+  writeOneTypeOneOperandLayout(I->getKind(), attrs, I->getType(),
+                               I->getOperand(0));
 }
 
 void
@@ -1471,14 +1470,18 @@
   case SILInstructionKind::ObjCMetatypeToObjectInst:
   case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
   case SILInstructionKind::ProjectBlockStorageInst: {
-    bool guaranteed = false;
-    bool escaped = false;
+    unsigned attrs = 0;
     if (SI.getKind() == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
-      escaped = cast<ConvertEscapeToNoEscapeInst>(SI).isEscapedByUser();
-      guaranteed = cast<ConvertEscapeToNoEscapeInst>(SI).isLifetimeGuaranteed();
+      if (cast<ConvertEscapeToNoEscapeInst>(SI).isLifetimeGuaranteed())
+        attrs |= 0x01;
+      if (cast<ConvertEscapeToNoEscapeInst>(SI).isEscapedByUser())
+        attrs |= 0x02;
     }
-    writeConversionLikeInstruction(cast<SingleValueInstruction>(&SI),
-                                   guaranteed, escaped);
+    if (SI.getKind() == SILInstructionKind::ConvertFunctionInst) {
+      if (cast<ConvertFunctionInst>(SI).withoutActuallyEscaping())
+        attrs |= 0x01;
+    }
+    writeConversionLikeInstruction(cast<SingleValueInstruction>(&SI), attrs);
     break;
   }
   case SILInstructionKind::PointerToAddressInst: {
diff --git a/lib/Syntax/SyntaxArena.cpp b/lib/Syntax/SyntaxArena.cpp
index 65e5902..9efcf2f 100644
--- a/lib/Syntax/SyntaxArena.cpp
+++ b/lib/Syntax/SyntaxArena.cpp
@@ -75,16 +75,16 @@
   friend llvm::FoldingSetTrait<RawSyntaxCacheNode>;
 
   /// Associated RawSyntax.
-  RawSyntax *Obj;
+  RC<RawSyntax> Obj;
   /// FoldingSet node identifier of the associated RawSyntax.
   llvm::FoldingSetNodeIDRef IDRef;
 
 public:
-  RawSyntaxCacheNode(RawSyntax *Obj, const llvm::FoldingSetNodeIDRef IDRef)
+  RawSyntaxCacheNode(RC<RawSyntax> Obj, const llvm::FoldingSetNodeIDRef IDRef)
       : Obj(Obj), IDRef(IDRef) {}
 
   /// Retrieve assciated RawSyntax.
-  RawSyntax *get() { return Obj; }
+  RC<RawSyntax> get() { return Obj; }
 
   // Only allow allocation of Node using the allocator in SyntaxArena.
   void *operator new(size_t Bytes, SyntaxArena &Arena,
@@ -156,7 +156,7 @@
   auto Raw = RawSyntax::make(TokKind, Text, LeadingTrivia, TrailingTrivia,
                              SourcePresence::Present, &Arena);
   auto IDRef = ID.Intern(Arena.getAllocator());
-  auto CacheNode = new (Arena) RawSyntaxCacheNode(Raw.get(), IDRef);
+  auto CacheNode = new (Arena) RawSyntaxCacheNode(Raw, IDRef);
   CachedTokens.InsertNode(CacheNode, insertPos);
   return Raw;
 }
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index 9a5ce1c..74b5d26 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -233,7 +233,8 @@
   SyntaxFactory::make${token.name}Keyword(const Trivia &LeadingTrivia,
                                           const Trivia &TrailingTrivia,
                                           SyntaxArena *Arena) {
-    return makeToken(tok::${token.kind}, "${token.text}",
+    return makeToken(tok::${token.kind},
+                     OwnedString::makeUnowned("${token.text}"),
                      LeadingTrivia, TrailingTrivia,
                      SourcePresence::Present, Arena);
   }
@@ -242,7 +243,8 @@
   SyntaxFactory::make${token.name}Token(const Trivia &LeadingTrivia,
                                         const Trivia &TrailingTrivia,
                                         SyntaxArena *Arena) {
-    return makeToken(tok::${token.kind}, "${token.text}",
+    return makeToken(tok::${token.kind},
+                     OwnedString::makeUnowned("${token.text}"),
                      LeadingTrivia, TrailingTrivia,
                      SourcePresence::Present, Arena);
   }
@@ -303,30 +305,35 @@
 TypeSyntax SyntaxFactory::makeAnyTypeIdentifier(const Trivia &LeadingTrivia,
                                                 const Trivia &TrailingTrivia,
                                                 SyntaxArena *Arena) {
-  return makeTypeIdentifier("Any", LeadingTrivia, TrailingTrivia, Arena);
+  return makeTypeIdentifier(OwnedString::makeUnowned("Any"), LeadingTrivia,
+                            TrailingTrivia, Arena);
 }
 
 TypeSyntax SyntaxFactory::makeSelfTypeIdentifier(const Trivia &LeadingTrivia,
                                                  const Trivia &TrailingTrivia,
                                                  SyntaxArena *Arena) {
-  return makeTypeIdentifier("Self", LeadingTrivia, TrailingTrivia, Arena);
+  return makeTypeIdentifier(OwnedString::makeUnowned("Self"),
+                            LeadingTrivia, TrailingTrivia, Arena);
 }
 
 TokenSyntax SyntaxFactory::makeTypeToken(const Trivia &LeadingTrivia,
                                          const Trivia &TrailingTrivia,
                                          SyntaxArena *Arena) {
-  return makeIdentifier("Type", LeadingTrivia, TrailingTrivia, Arena);
+  return makeIdentifier(OwnedString::makeUnowned("Type"),
+                        LeadingTrivia, TrailingTrivia, Arena);
 }
 
 TokenSyntax SyntaxFactory::makeProtocolToken(const Trivia &LeadingTrivia,
                                              const Trivia &TrailingTrivia,
                                              SyntaxArena *Arena) {
-  return makeIdentifier("Protocol", LeadingTrivia, TrailingTrivia, Arena);
+  return makeIdentifier(OwnedString::makeUnowned("Protocol"),
+                        LeadingTrivia, TrailingTrivia, Arena);
 }
 
 TokenSyntax SyntaxFactory::makeEqualityOperator(const Trivia &LeadingTrivia,
                                                 const Trivia &TrailingTrivia,
                                                 SyntaxArena *Arena) {
-  return makeToken(tok::oper_binary_spaced, "==", LeadingTrivia, TrailingTrivia,
-                   SourcePresence::Present, Arena);
+  return makeToken(tok::oper_binary_spaced, OwnedString::makeUnowned("=="),
+                   LeadingTrivia, TrailingTrivia, SourcePresence::Present,
+                   Arena);
 }
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index 42ae96e..f90fd8d 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -658,7 +658,7 @@
 struct UnaryOp {}
 
 _ = -UnaryOp() // expected-error {{unary operator '-' cannot be applied to an operand of type 'UnaryOp'}}
-// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Float), (Double), (Float80)}}
+// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Float), (Double)}}
 
 
 // <rdar://problem/23433271> Swift compiler segfault in failure diagnosis
diff --git a/test/IRGen/empty_enum.swift b/test/IRGen/empty_enum.swift
new file mode 100644
index 0000000..8553135
--- /dev/null
+++ b/test/IRGen/empty_enum.swift
@@ -0,0 +1,6 @@
+// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s
+
+// CHECK: @"$S10empty_enum6JamaisOMf" =
+//   CHECK-SAME: @"$SytWV"
+
+enum Jamais {}
diff --git a/test/IRGen/objc_ns_enum.swift b/test/IRGen/objc_ns_enum.swift
index e9ad416..6c32906 100644
--- a/test/IRGen/objc_ns_enum.swift
+++ b/test/IRGen/objc_ns_enum.swift
@@ -8,9 +8,9 @@
 import Foundation
 import gizmo
 
-// CHECK: @"$SSo16NSRuncingOptionsVWV" = linkonce_odr hidden constant
 // CHECK: @"$SSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant
 // CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden constant
+//   CHECK-SAME: @"$SBi{{[0-9]+}}_WV"
 // CHECK: @"$SSo16NSRuncingOptionsVSQSCMc" = linkonce_odr hidden constant %swift.protocol_conformance_descriptor { {{.*}}@"$SSo16NSRuncingOptionsVSQSCWa
 // CHECK: @"$SSo28NeverActuallyMentionedByNameVSQSCWp" = linkonce_odr hidden constant
 
diff --git a/test/SIL/Parser/without_actually_escaping.sil b/test/SIL/Parser/without_actually_escaping.sil
new file mode 100644
index 0000000..2758e05
--- /dev/null
+++ b/test/SIL/Parser/without_actually_escaping.sil
@@ -0,0 +1,32 @@
+// RUN: %target-sil-opt %s | %FileCheck %s
+
+// thunk for @escaping @callee_guaranteed () -> ()
+// Check that the [without_actually_escaping] thunk attribute is parsed and printed.
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @testWithoutActuallyEscapingThunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @testWithoutActuallyEscapingThunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
+  %1 = apply %0() : $@callee_guaranteed () -> ()
+  return %1 : $()
+}
+
+// Check that the convert_function [without_actually_escaping] attribute is parsed and printed.
+// CHECK-LABEL: sil hidden @testWithoutActuallyEscapingBlock : $@convention(thin) (@guaranteed @convention(block) @noescape () -> ()) -> () {
+// CHECK: convert_function %0 : $@convention(block) @noescape () -> () to [without_actually_escaping] $@convention(block) () -> ()
+sil hidden @testWithoutActuallyEscapingBlock : $@convention(thin) (@guaranteed @convention(block) @noescape () -> ()) -> () {
+bb0(%0 : @guaranteed $@convention(block) @noescape () -> ()):
+  %cvt = convert_function %0 : $@convention(block) @noescape () -> () to [without_actually_escaping] $@convention(block) () -> ()
+  %f = function_ref @closure1 : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  %call = apply %f(%cvt) : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  destroy_value %cvt : $@convention(block) () -> ()
+  %v = tuple ()
+  return %v : $()
+}
+
+// closure #1 in testBlock(block:)
+sil private @closure1 : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> () {
+bb0(%0 : @guaranteed $@convention(block) () -> ()):
+  %call = apply %0() : $@convention(block) () -> ()
+  %v = tuple ()
+  return %v : $()
+}
+
diff --git a/test/SIL/Serialization/without_actually_escaping.sil b/test/SIL/Serialization/without_actually_escaping.sil
new file mode 100644
index 0000000..77af896
--- /dev/null
+++ b/test/SIL/Serialization/without_actually_escaping.sil
@@ -0,0 +1,36 @@
+// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
+// RUN: %empty-directory(%t)
+// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name without_actually_escaping
+// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name without_actually_escaping
+// RUN: %target-sil-opt %t/tmp.2.sib -module-name without_actually_escaping | %FileCheck %s
+
+// thunk for @escaping @callee_guaranteed () -> ()
+// Check that the [without_actually_escaping] thunk attribute is parsed and printed.
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @f1_testWithoutActuallyEscapingThunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @f1_testWithoutActuallyEscapingThunk : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
+  %1 = apply %0() : $@callee_guaranteed () -> ()
+  return %1 : $()
+}
+
+// Check that the convert_function [without_actually_escaping] attribute is parsed and printed.
+// CHECK-LABEL: sil hidden @f2_testWithoutActuallyEscapingBlock : $@convention(thin) (@guaranteed @convention(block) @noescape () -> ()) -> () {
+// CHECK: convert_function %0 : $@convention(block) @noescape () -> () to [without_actually_escaping] $@convention(block) () -> ()
+sil hidden @f2_testWithoutActuallyEscapingBlock : $@convention(thin) (@guaranteed @convention(block) @noescape () -> ()) -> () {
+bb0(%0 : @guaranteed $@convention(block) @noescape () -> ()):
+  %cvt = convert_function %0 : $@convention(block) @noescape () -> () to [without_actually_escaping] $@convention(block) () -> ()
+  %f = function_ref @closure1 : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  %call = apply %f(%cvt) : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  destroy_value %cvt : $@convention(block) () -> ()
+  %v = tuple ()
+  return %v : $()
+}
+
+// closure #1 in testBlock(block:)
+sil private @closure1 : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> () {
+bb0(%0 : @guaranteed $@convention(block) () -> ()):
+  %call = apply %0() : $@convention(block) () -> ()
+  %v = tuple ()
+  return %v : $()
+}
+
diff --git a/test/SILGen/without_actually_escaping.swift b/test/SILGen/without_actually_escaping.swift
index 3e00ff0..78372c4 100644
--- a/test/SILGen/without_actually_escaping.swift
+++ b/test/SILGen/without_actually_escaping.swift
@@ -6,8 +6,9 @@
 // CHECK-LABEL: sil hidden @$S25without_actually_escaping9letEscape1fyycyyXE_tF
 func letEscape(f: () -> ()) -> () -> () {
   // CHECK: bb0([[ARG:%.*]] : @trivial $@noescape @callee_guaranteed () -> ()):
+  // CHECK: [[THUNK:%.*]] = function_ref @$SIg_Ieg_TR : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
   // TODO: Use a canary wrapper instead of just copying the nonescaping value
-  // CHECK: [[ESCAPABLE_COPY:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[ARG]])
+  // CHECK: [[ESCAPABLE_COPY:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG]])
   // CHECK: [[MD_ESCAPABLE_COPY:%.*]] = mark_dependence [[ESCAPABLE_COPY]]
   // CHECK: [[BORROW_MD_ESCAPABLE_COPY:%.*]] = begin_borrow [[MD_ESCAPABLE_COPY]]
   // CHECK: [[SUB_CLOSURE:%.*]] = function_ref @
@@ -17,6 +18,9 @@
   return withoutActuallyEscaping(f) { return $0 }
 }
 
+// thunk for @callee_guaranteed () -> ()
+// The thunk must be [without_actually_escaping].
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @$SIg_Ieg_TR : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () {
 
 // CHECK-LABEL: sil hidden @$S25without_actually_escaping14letEscapeThrow1fyycyycyKXE_tKF
 // CHECK: bb0([[ARG:%.*]] : @trivial $@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error Error)):
@@ -44,6 +48,10 @@
   return try withoutActuallyEscaping(f) { return try $0() }
 }
 
+// thunk for @callee_guaranteed () -> (@owned @escaping @callee_guaranteed () -> (), @error @owned Error)
+// The thunk must be [without_actually_escaping].
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @$SIeg_s5Error_pIgozo_Ieg_sAA_pIegozo_TR : $@convention(thin) (@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error Error)) -> (@owned @callee_guaranteed () -> (), @error Error) {
+
 // We used to crash on this example because we would use the wrong substitution
 // map.
 struct DontCrash {
diff --git a/test/SILGen/without_actually_escaping_block.swift b/test/SILGen/without_actually_escaping_block.swift
index 8001c52..be7c5ae 100644
--- a/test/SILGen/without_actually_escaping_block.swift
+++ b/test/SILGen/without_actually_escaping_block.swift
@@ -13,7 +13,7 @@
 // CHECK:  [[C1:%.*]] = copy_block [[ARG]]
 // CHECK:  [[B1:%.*]] = begin_borrow [[C1]]
 // CHECK:  [[C2:%.*]] = copy_value [[B1]]
-// CHECK:  [[CVT:%.*]] = convert_function [[C2]] : $@convention(block) @noescape () -> () to $@convention(block) () -> ()
+// CHECK:  [[CVT:%.*]] = convert_function [[C2]] : $@convention(block) @noescape () -> () to [without_actually_escaping] $@convention(block) () -> ()
 // CHECK:  [[B2:%.*]] = begin_borrow [[CVT]]
 // CHECK:  [[FN:%.*]] = function_ref @$S25without_actually_escaping9testBlock5blockyyyXB_tFyyyXBXEfU_
 // CHECK:  apply [[FN]]([[B2]])
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics.sil b/test/SILOptimizer/exclusivity_static_diagnostics.sil
index d2c1b5b..7259184 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics.sil
+++ b/test/SILOptimizer/exclusivity_static_diagnostics.sil
@@ -1285,3 +1285,116 @@
   %v = tuple ()
   return %v : $()
 }
+
+// -----------------------------------------------------------------------------
+// Test withoutActuallyEscaping thunk.
+// <rdar://problem/43059088> Assertion in DiagnoseStaticExclusivity
+// Noescape closure verification should not assert.
+
+sil @takeEscapingClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+
+sil private @nestedInWithoutActuallyEscapingVerify : $@convention(thin) (@inout_aliasable Int) -> () {
+bb0(%0 : @trivial $*Int):
+  %a = begin_access [modify] [unknown] %0 : $*Int
+  end_access %a : $*Int
+  %v = tuple ()
+  return %v : $()
+}
+
+// CHECK-LABEL: sil hidden @testWithoutActuallyEscapingVerify : $@convention(thin) (@inout Int) -> () {
+sil hidden @testWithoutActuallyEscapingVerify : $@convention(thin) (@inout Int) -> () {
+bb0(%0 : @trivial $*Int):
+  %2 = function_ref @nestedInWithoutActuallyEscapingVerify : $@convention(thin) (@inout_aliasable Int) -> ()
+  %3 = partial_apply [callee_guaranteed] %2(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
+
+  %4 = function_ref @thunkForWithoutActuallyEscapingVerify : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %5 = partial_apply [callee_guaranteed] %4(%3) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %6 = mark_dependence %5 : $@callee_guaranteed () -> () on %3 : $@callee_guaranteed () -> ()
+
+  %8 = function_ref @closureForWithoutActuallyEscapingVerify : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %9 = apply %8(%6) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %10 = is_escaping_closure %6 : $@callee_guaranteed () -> ()
+  cond_fail %10 : $Builtin.Int1
+  destroy_value %6 : $@callee_guaranteed () -> ()
+  %14 = tuple ()
+  return %14 : $()
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @thunkForWithoutActuallyEscapingVerify : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+sil shared [transparent] [serializable] [reabstraction_thunk] [without_actually_escaping] @thunkForWithoutActuallyEscapingVerify : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
+  %1 = apply %0() : $@callee_guaranteed () -> ()
+  return %1 : $()
+}
+
+sil private @closureForWithoutActuallyEscapingVerify : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
+  %2 = function_ref @takeEscapingClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %3 = apply %2(%0) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
+  %4 = tuple ()
+  return %4 : $()
+}
+
+// -----------------------------------------------------------------------------
+// Test withoutActuallyEscaping convert_function.
+// <rdar://problem/43059088> Assertion in DiagnoseStaticExclusivity
+// Noescape closure verification should not assert.
+
+// CHECK-LABEL: sil hidden @testWithoutActuallyEscapingBlockVerify : $@convention(thin) (Int) -> () {
+// CHECK: convert_function %{{.*}} : $@convention(block) () -> () to [without_actually_escaping] $@convention(block) () -> ()
+sil hidden @testWithoutActuallyEscapingBlockVerify : $@convention(thin) (Int) -> () {
+bb0(%0 : @trivial $Int):
+  %box = alloc_box ${ var Int }, var, name "localVal"
+  %projbox = project_box %box : ${ var Int }, 0
+  store %0 to [trivial] %projbox : $*Int
+  %closureF = function_ref @testWithoutActuallyEscapingBlockVerifyClosure : $@convention(thin) (@inout_aliasable Int) -> ()
+  %closure = partial_apply [callee_guaranteed] %closureF(%projbox) : $@convention(thin) (@inout_aliasable Int) -> ()
+  %block = alloc_stack $@block_storage @callee_guaranteed () -> ()
+  %blockproj = project_block_storage %block : $*@block_storage @callee_guaranteed () -> ()
+  store %closure to [init] %blockproj : $*@callee_guaranteed () -> ()
+  // function_ref thunk for @escaping @callee_guaranteed () -> ()
+  %thunkF = function_ref @$SIeg_IeyB_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
+  %initblock = init_block_storage_header %block : $*@block_storage @callee_guaranteed () -> (), invoke %thunkF : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> (), type $@convention(block) () -> ()
+  destroy_addr %blockproj : $*@callee_guaranteed () -> ()
+  dealloc_stack %block : $*@block_storage @callee_guaranteed () -> ()
+  %borrow = begin_borrow %initblock : $@convention(block) () -> ()
+  %copy = copy_value %borrow : $@convention(block) () -> ()
+  %escapingF = convert_function %copy : $@convention(block) () -> () to [without_actually_escaping] $@convention(block) () -> ()
+  %clauseF = function_ref @testWithoutActuallyEscapingBlockVerifyClause : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  %call = apply %clauseF(%escapingF) : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> ()
+  destroy_value %escapingF : $@convention(block) () -> ()
+  end_borrow %borrow from %initblock : $@convention(block) () -> (), $@convention(block) () -> ()
+  destroy_value %initblock : $@convention(block) () -> ()
+  destroy_value %box : ${ var Int }
+  %v = tuple ()
+  return %v : $()
+}
+
+sil @testWithoutActuallyEscapingBlockVerifyClosure : $@convention(thin) (@inout_aliasable Int) -> ()
+
+// thunk for @escaping @callee_guaranteed () -> ()
+sil shared [transparent] [serializable] [reabstraction_thunk] @$SIeg_IeyB_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> () {
+// %0
+bb0(%0 : @trivial $*@block_storage @callee_guaranteed () -> ()):
+  %1 = project_block_storage %0 : $*@block_storage @callee_guaranteed () -> ()
+  %2 = load [copy] %1 : $*@callee_guaranteed () -> ()
+  %3 = begin_borrow %2 : $@callee_guaranteed () -> ()
+  %4 = apply %3() : $@callee_guaranteed () -> ()
+  end_borrow %3 from %2 : $@callee_guaranteed () -> (), $@callee_guaranteed () -> ()
+  %6 = tuple ()
+  destroy_value %2 : $@callee_guaranteed () -> ()
+  return %6 : $()
+} // end sil function '$SIeg_IeyB_TR'
+
+sil private @testWithoutActuallyEscapingBlockVerifyClause : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> () {
+bb0(%0 : @guaranteed $@convention(block) () -> ()):
+  %1 = copy_block %0 : $@convention(block) () -> ()
+  %3 = begin_borrow %1 : $@convention(block) () -> ()
+  %4 = copy_value %3 : $@convention(block) () -> ()
+  %5 = apply %4() : $@convention(block) () -> ()
+  destroy_value %4 : $@convention(block) () -> ()
+  end_borrow %3 from %1 : $@convention(block) () -> (), $@convention(block) () -> ()
+  destroy_value %1 : $@convention(block) () -> ()
+  %v = tuple ()
+  return %v : $()
+}
diff --git a/test/api-digester/Outputs/cake-abi.json b/test/api-digester/Outputs/cake-abi.json
new file mode 100644
index 0000000..3a068eb
--- /dev/null
+++ b/test/api-digester/Outputs/cake-abi.json
@@ -0,0 +1,729 @@
+{
+  "kind": "Root",
+  "name": "TopLevel",
+  "printedName": "TopLevel",
+  "children": [
+    {
+      "kind": "TypeDecl",
+      "name": "P1",
+      "printedName": "P1",
+      "declKind": "Protocol",
+      "usr": "s:4cake2P1P",
+      "location": "",
+      "moduleName": "cake"
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "P2",
+      "printedName": "P2",
+      "declKind": "Protocol",
+      "usr": "s:4cake2P2P",
+      "location": "",
+      "moduleName": "cake"
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "S1",
+      "printedName": "S1",
+      "declKind": "Struct",
+      "usr": "s:4cake2S1V",
+      "location": "",
+      "moduleName": "cake",
+      "conformingProtocols": [
+        "P1",
+        "P2"
+      ],
+      "declAttributes": [
+        "FixedLayout"
+      ],
+      "children": [
+        {
+          "kind": "Function",
+          "name": "foo1",
+          "printedName": "foo1()",
+          "declKind": "Func",
+          "usr": "s:4cake2S1V4foo1yyFZ",
+          "location": "",
+          "moduleName": "cake",
+          "static": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        },
+        {
+          "kind": "Function",
+          "name": "foo2",
+          "printedName": "foo2()",
+          "declKind": "Func",
+          "usr": "s:4cake2S1V4foo2yyF",
+          "location": "",
+          "moduleName": "cake",
+          "mutating": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        },
+        {
+          "kind": "Function",
+          "name": "foo6",
+          "printedName": "foo6()",
+          "declKind": "Func",
+          "usr": "s:4cake2S1V4foo6yyF",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init()",
+          "declKind": "Constructor",
+          "usr": "s:4cake2S1VACycfc",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "S1",
+              "printedName": "S1",
+              "usr": "s:4cake2S1V"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "C0",
+      "printedName": "C0",
+      "declKind": "Class",
+      "usr": "s:4cake2C0C",
+      "location": "",
+      "moduleName": "cake",
+      "genericSig": "<τ_0_0, τ_0_1, τ_0_2>",
+      "children": [
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init()",
+          "declKind": "Constructor",
+          "usr": "s:4cake2C0CACyxq_q0_Gycfc",
+          "location": "",
+          "moduleName": "cake",
+          "genericSig": "<τ_0_0, τ_0_1, τ_0_2>",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "C0",
+              "printedName": "C0<τ_0_0, τ_0_1, τ_0_2>",
+              "usr": "s:4cake2C0C",
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "GenericTypeParam",
+                  "printedName": "τ_0_0"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "GenericTypeParam",
+                  "printedName": "τ_0_1"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "GenericTypeParam",
+                  "printedName": "τ_0_2"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Function",
+          "name": "conditionalFooExt",
+          "printedName": "conditionalFooExt()",
+          "declKind": "Func",
+          "usr": "s:4cake2C0CA2A2S1VRszAERs_AERs0_rlE17conditionalFooExtyyF",
+          "location": "",
+          "moduleName": "cake",
+          "genericSig": "<τ_0_0, τ_0_1, τ_0_2 where τ_0_0 == S1, τ_0_1 == S1, τ_0_2 == S1>",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        },
+        {
+          "kind": "Function",
+          "name": "unconditionalFooExt",
+          "printedName": "unconditionalFooExt()",
+          "declKind": "Func",
+          "usr": "s:4cake2C0C19unconditionalFooExtyyF",
+          "location": "",
+          "moduleName": "cake",
+          "genericSig": "<τ_0_0, τ_0_1, τ_0_2>",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "C1",
+      "printedName": "C1",
+      "declKind": "Class",
+      "usr": "s:4cake2C1C",
+      "location": "",
+      "moduleName": "cake",
+      "superclassUsr": "s:4cake2C0C",
+      "children": [
+        {
+          "kind": "Function",
+          "name": "foo1",
+          "printedName": "foo1()",
+          "declKind": "Func",
+          "usr": "s:4cake2C1C4foo1yyFZ",
+          "location": "",
+          "moduleName": "cake",
+          "static": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "Ins",
+          "printedName": "Ins",
+          "declKind": "Var",
+          "usr": "s:4cake2C1C3InsACSgXwvp",
+          "location": "",
+          "moduleName": "cake",
+          "declAttributes": [
+            "HasInitialValue",
+            "ReferenceOwnership"
+          ],
+          "ownership": 1,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "WeakStorage",
+              "printedName": "Optional<C1>"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake2C1C3InsACSgXwvg",
+              "location": "",
+              "moduleName": "cake",
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Optional",
+                  "printedName": "Optional<C1>",
+                  "usr": "s:Sq",
+                  "children": [
+                    {
+                      "kind": "TypeNominal",
+                      "name": "C1",
+                      "printedName": "C1",
+                      "usr": "s:4cake2C1C"
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake2C1C3InsACSgXwvs",
+              "location": "",
+              "moduleName": "cake",
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Optional",
+                  "printedName": "Optional<C1>",
+                  "usr": "s:Sq",
+                  "children": [
+                    {
+                      "kind": "TypeNominal",
+                      "name": "C1",
+                      "printedName": "C1",
+                      "usr": "s:4cake2C1C"
+                    }
+                  ]
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "Ins2",
+          "printedName": "Ins2",
+          "declKind": "Var",
+          "usr": "s:4cake2C1C4Ins2ACXovp",
+          "location": "",
+          "moduleName": "cake",
+          "declAttributes": [
+            "HasInitialValue",
+            "ReferenceOwnership"
+          ],
+          "ownership": 2,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "UnownedStorage",
+              "printedName": "C1"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake2C1C4Ins2ACXovg",
+              "location": "",
+              "moduleName": "cake",
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "C1",
+                  "printedName": "C1",
+                  "usr": "s:4cake2C1C"
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake2C1C4Ins2ACXovs",
+              "location": "",
+              "moduleName": "cake",
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "C1",
+                  "printedName": "C1",
+                  "usr": "s:4cake2C1C"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init()",
+          "declKind": "Constructor",
+          "usr": "s:4cake2C1CACycfc",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "C1",
+              "printedName": "C1",
+              "usr": "s:4cake2C1C"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "Function",
+      "name": "foo1",
+      "printedName": "foo1(_:b:)",
+      "declKind": "Func",
+      "usr": "s:4cake4foo1_1bySi_AA2S1VtF",
+      "location": "",
+      "moduleName": "cake",
+      "children": [
+        {
+          "kind": "TypeNominal",
+          "name": "Void",
+          "printedName": "()"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "Int",
+          "printedName": "Int",
+          "hasDefaultArg": true,
+          "usr": "s:Si"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "S1",
+          "printedName": "S1",
+          "usr": "s:4cake2S1V"
+        }
+      ]
+    },
+    {
+      "kind": "Function",
+      "name": "foo2",
+      "printedName": "foo2(_:b:)",
+      "declKind": "Func",
+      "usr": "s:4cake4foo2_1bySi_AA2S1VtF",
+      "location": "",
+      "moduleName": "cake",
+      "children": [
+        {
+          "kind": "TypeNominal",
+          "name": "Void",
+          "printedName": "()"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "Int",
+          "printedName": "Int",
+          "hasDefaultArg": true,
+          "usr": "s:Si"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "S1",
+          "printedName": "S1",
+          "usr": "s:4cake2S1V"
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "Number",
+      "printedName": "Number",
+      "declKind": "Enum",
+      "usr": "s:4cake6NumberO",
+      "location": "",
+      "moduleName": "cake",
+      "conformingProtocols": [
+        "Equatable",
+        "Hashable",
+        "RawRepresentable"
+      ],
+      "enumRawTypeName": "Int",
+      "children": [
+        {
+          "kind": "Var",
+          "name": "one",
+          "printedName": "one",
+          "declKind": "EnumElement",
+          "usr": "s:4cake6NumberO3oneyA2CmF",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeFunc",
+              "name": "Function",
+              "printedName": "(Number.Type) -> Number",
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Number",
+                  "printedName": "Number",
+                  "usr": "s:4cake6NumberO"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Metatype",
+                  "printedName": "Number.Type",
+                  "children": [
+                    {
+                      "kind": "TypeNominal",
+                      "name": "Number",
+                      "printedName": "Number",
+                      "usr": "s:4cake6NumberO"
+                    }
+                  ]
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "TypeAlias",
+          "name": "RawValue",
+          "printedName": "RawValue",
+          "declKind": "TypeAlias",
+          "usr": "s:4cake6NumberO8RawValuea",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "hashValue",
+          "printedName": "hashValue",
+          "declKind": "Var",
+          "usr": "s:4cake6NumberO9hashValueSivp",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake6NumberO9hashValueSivg",
+              "location": "",
+              "moduleName": "cake",
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Function",
+          "name": "hash",
+          "printedName": "hash(into:)",
+          "declKind": "Func",
+          "usr": "s:4cake6NumberO4hash4intoys6HasherVz_tF",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Hasher",
+              "printedName": "Hasher",
+              "usr": "s:s6HasherV"
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init(rawValue:)",
+          "declKind": "Constructor",
+          "usr": "s:4cake6NumberO8rawValueACSgSi_tcfc",
+          "location": "",
+          "moduleName": "cake",
+          "declAttributes": [
+            "Inlinable"
+          ],
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Optional",
+              "printedName": "Optional<Number>",
+              "usr": "s:Sq",
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Number",
+                  "printedName": "Number",
+                  "usr": "s:4cake6NumberO"
+                }
+              ]
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "rawValue",
+          "printedName": "rawValue",
+          "declKind": "Var",
+          "usr": "s:4cake6NumberO8rawValueSivp",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake6NumberO8rawValueSivg",
+              "location": "",
+              "moduleName": "cake",
+              "declAttributes": [
+                "Inlinable"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "Function",
+      "name": "foo3",
+      "printedName": "foo3(_:)",
+      "declKind": "Func",
+      "usr": "s:4cake4foo3yySDySiSSGF",
+      "location": "",
+      "moduleName": "cake",
+      "children": [
+        {
+          "kind": "TypeNominal",
+          "name": "Void",
+          "printedName": "()"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "Dictionary",
+          "printedName": "Dictionary<Int, String>",
+          "usr": "s:SD",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "String",
+              "printedName": "String",
+              "usr": "s:SS"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
+      "name": "Int",
+      "printedName": "Int",
+      "declKind": "Struct",
+      "usr": "s:Si",
+      "location": "",
+      "moduleName": "Swift",
+      "conformingProtocols": [
+        "Comparable",
+        "SignedInteger",
+        "_ExpressibleByBuiltinIntegerLiteral",
+        "BinaryInteger",
+        "LosslessStringConvertible",
+        "SignedNumeric",
+        "Numeric",
+        "CustomStringConvertible",
+        "Strideable",
+        "ExpressibleByIntegerLiteral",
+        "FixedWidthInteger",
+        "Encodable",
+        "Decodable",
+        "Hashable",
+        "Equatable",
+        "_HasCustomAnyHashableRepresentation",
+        "CustomReflectable",
+        "_CustomPlaygroundQuickLookable",
+        "MirrorPath",
+        "CVarArg"
+      ],
+      "declAttributes": [
+        "FixedLayout"
+      ],
+      "children": [
+        {
+          "kind": "Function",
+          "name": "foo",
+          "printedName": "foo()",
+          "declKind": "Func",
+          "usr": "s:Si4cakeE3fooyyF",
+          "location": "",
+          "moduleName": "cake",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Void",
+              "printedName": "()"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/api-digester/dump-module.swift b/test/api-digester/dump-module.swift
index 4732f1c..e88d93a 100644
--- a/test/api-digester/dump-module.swift
+++ b/test/api-digester/dump-module.swift
@@ -4,8 +4,12 @@
 // RUN: %swift -emit-module -o %t.mod/cake.swiftmodule %S/Inputs/cake.swift -parse-as-library
 // RUN: %api-digester -dump-sdk -module cake -o %t.dump.json -module-cache-path %t.module-cache -sdk %t.sdk -I %t.mod
 // RUN: diff -u %S/Outputs/cake.json %t.dump.json
+// RUN: %api-digester -dump-sdk -module cake -o %t.dump.json -module-cache-path %t.module-cache -sdk %t.sdk -I %t.mod -abi
+// RUN: diff -u %S/Outputs/cake-abi.json %t.dump.json
 // RUN: %api-digester -diagnose-sdk --input-paths %t.dump.json -input-paths %S/Outputs/cake.json
 
 // Round-trip testing:
 // RUN: %api-digester -deserialize-sdk --input-paths %S/Outputs/cake.json -o %t.dump.json
 // RUN: diff -u %S/Outputs/cake.json %t.dump.json
+// RUN: %api-digester -deserialize-sdk --input-paths %S/Outputs/cake-abi.json -o %t.dump.json
+// RUN: diff -u %S/Outputs/cake-abi.json %t.dump.json
diff --git a/test/lit.cfg b/test/lit.cfg
index 1aabb68..935d310 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -940,6 +940,50 @@
     'appletvsimulator': SIMULATOR_ENV_PREFIX
 }
 TARGET_ENV_PREFIX = ENV_VAR_PREFIXES.get(config.target_sdk_name, "")
+
+if not config.target_run and 'remote_run_host' in lit_config.params:
+    if 'remote_run_tmpdir' not in lit_config.params:
+        lit_config.fatal("'remote_run_host' provided, but no "
+                         "'remote_run_tmpdir'")
+
+    remote_run_host = lit_config.params['remote_run_host']
+    remote_tmp_dir = lit_config.params['remote_run_tmpdir']
+    remote_lib_dir = os.path.join(remote_tmp_dir, 'stdlib')
+    if 'remote_run_identity' in lit_config.params:
+        identity_args = ['-i', lit_config.params['remote_run_identity']]
+    else:
+        identity_args = []
+
+    if 'remote_run_skip_upload_stdlib' not in lit_config.params:
+        lit_config.note(
+            "Uploading dylibs to {0} on {1}".format(remote_lib_dir,
+                                                    remote_run_host))
+        sdk_lib_dir = os.path.join(test_resource_dir, config.target_sdk_name)
+        glob_pattern = os.path.join(sdk_lib_dir,
+                                    '*.' + config.target_dylib_extension)
+        libs = glob.glob(glob_pattern)
+        subprocess.check_call(
+            [
+                os.path.join(config.swift_utils, 'remote-run'),
+                '--remote-dir', remote_tmp_dir,
+                '--input-prefix', sdk_lib_dir,
+                '--remote-input-prefix', 'stdlib/'
+            ] + identity_args + [
+                remote_run_host,
+                '--',
+                'true' # A dummy command that ignores its arguments.
+            ] + libs)
+
+    config.target_run = (
+        "/usr/bin/env "
+        "REMOTE_RUN_CHILD_DYLD_FALLBACK_LIBRARY_PATH='{0}' " # Apple option
+        "REMOTE_RUN_CHILD_LD_LIBRARY_PATH='{0}' " # Linux option
+        "%utils/remote-run --input-prefix %S --output-prefix %t "
+        "--remote-dir '{1}'%t {2} {3}".format(remote_lib_dir, remote_tmp_dir,
+                                              ' '.join(identity_args),
+                                              remote_run_host))
+    TARGET_ENV_PREFIX = 'REMOTE_RUN_CHILD_'
+
 config.substitutions.append(('%env-', TARGET_ENV_PREFIX))
 config.substitutions.append(("%target-sdk-name", config.target_sdk_name))
 
diff --git a/test/remote-run/Inputs/upload/1.txt b/test/remote-run/Inputs/upload/1.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/remote-run/Inputs/upload/1.txt
diff --git a/test/remote-run/Inputs/upload/2.txt b/test/remote-run/Inputs/upload/2.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/remote-run/Inputs/upload/2.txt
diff --git a/test/remote-run/Inputs/upload/BAD.txt b/test/remote-run/Inputs/upload/BAD.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/remote-run/Inputs/upload/BAD.txt
diff --git a/test/remote-run/download.test-sh b/test/remote-run/download.test-sh
new file mode 100644
index 0000000..78b6f99
--- /dev/null
+++ b/test/remote-run/download.test-sh
@@ -0,0 +1,14 @@
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t-REMOTE)
+RUN: %debug-remote-run --output-prefix %t touch %t/output
+RUN: ls %t/ | %FileCheck %s
+RUN: ls %t-REMOTE/output/ | %FileCheck %s
+
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t/nested)
+RUN: %empty-directory(%t-REMOTE)
+RUN: %debug-remote-run --output-prefix %t touch %t/nested/output
+RUN: ls %t/nested/ | %FileCheck %s
+RUN: ls %t-REMOTE/output/nested/ | %FileCheck %s
+
+CHECK: {{^output$}}
diff --git a/test/remote-run/dry-run-remote.test-sh b/test/remote-run/dry-run-remote.test-sh
new file mode 100644
index 0000000..020c3f3
--- /dev/null
+++ b/test/remote-run/dry-run-remote.test-sh
@@ -0,0 +1,25 @@
+RUN: %utils/remote-run -n --remote-dir /xyz-REMOTE --input-prefix %S/Inputs/ some_user@some_host ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt 2>&1 >/dev/null | %FileCheck -check-prefix CHECK-INPUT %s
+
+CHECK-INPUT: /usr/bin/ssh -n some_user@some_host -- '/usr/bin/env' '/bin/mkdir' '-p' '{{.+}}-REMOTE/input/upload'
+CHECK-INPUT-NEXT: /usr/bin/sftp
+CHECK-INPUT-SAME: some_user@some_host
+CHECK-INPUT-DAG: -put '{{.+}}/Inputs/upload/1.txt' '/xyz-REMOTE/input/upload/1.txt'
+CHECK-INPUT-DAG: -put '{{.+}}/Inputs/upload/2.txt' '/xyz-REMOTE/input/upload/2.txt'
+CHECK-INPUT: /usr/bin/ssh -n some_user@some_host -- '/usr/bin/env' 'ls'
+
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t/nested)
+RUN: touch %t/nested/input %t/nested/BAD
+RUN: %utils/remote-run -n --remote-dir /xyz-REMOTE --output-prefix %t some_user@some_host cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck -check-prefix CHECK-OUTPUT %s
+
+CHECK-OUTPUT: /usr/bin/ssh -n some_user@some_host -- '/usr/bin/env' '/bin/mkdir' '-p' '{{.+}}-REMOTE/output/nested'
+CHECK-OUTPUT-NEXT: /usr/bin/sftp
+CHECK-OUTPUT-SAME: some_user@some_host
+CHECK-OUTPUT-DAG: -put '{{.+}}/nested/output' '/xyz-REMOTE/output/nested/output'
+CHECK-OUTPUT-DAG: -put '{{.+}}/nested/input' '/xyz-REMOTE/output/nested/input'
+CHECK-OUTPUT: /usr/bin/ssh -n some_user@some_host -- '/usr/bin/env' 'cp'
+CHECK-OUTPUT-NEXT: {{^}}/bin/mkdir -p {{.+}}/nested
+CHECK-OUTPUT-NEXT: /usr/bin/sftp
+CHECK-OUTPUT-SAME: some_user@some_host
+CHECK-OUTPUT-DAG: -get '/xyz-REMOTE/output/nested/output' '{{.+}}/nested/output'
+CHECK-OUTPUT-DAG: -get '/xyz-REMOTE/output/nested/input' '{{.+}}/nested/input'
diff --git a/test/remote-run/dry-run.test-sh b/test/remote-run/dry-run.test-sh
new file mode 100644
index 0000000..c8b47b1
--- /dev/null
+++ b/test/remote-run/dry-run.test-sh
@@ -0,0 +1,26 @@
+RUN: %empty-directory(%t)
+RUN: %debug-remote-run -n --input-prefix %S/Inputs/ ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt 2>&1 >/dev/null | %FileCheck -check-prefix CHECK-INPUT %s
+RUN: test -z "`ls %t`"
+RUN: test ! -e %t-REMOTE
+
+CHECK-INPUT: /usr/bin/env /bin/mkdir -p {{.+}}-REMOTE/input/upload
+CHECK-INPUT-NEXT: /usr/bin/sftp
+CHECK-INPUT-DAG: -put '{{.+}}/Inputs/upload/1.txt' '{{.+}}-REMOTE/input/upload/1.txt'
+CHECK-INPUT-DAG: -put '{{.+}}/Inputs/upload/2.txt' '{{.+}}-REMOTE/input/upload/2.txt'
+CHECK-INPUT: /usr/bin/env ls
+
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t/nested)
+RUN: touch %t/nested/input %t/nested/BAD
+RUN: %debug-remote-run -n --output-prefix %t cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck -check-prefix CHECK-OUTPUT %s
+RUN: test ! -e %t-REMOTE
+
+CHECK-OUTPUT: /usr/bin/env /bin/mkdir -p {{.+}}-REMOTE/output/nested
+CHECK-OUTPUT-NEXT: /usr/bin/sftp
+CHECK-OUTPUT-DAG: -put '{{.+}}/nested/output' '{{.+}}-REMOTE/output/nested/output'
+CHECK-OUTPUT-DAG: -put '{{.+}}/nested/input' '{{.+}}-REMOTE/output/nested/input'
+CHECK-OUTPUT: /usr/bin/env cp
+CHECK-OUTPUT-NEXT: {{^}}/bin/mkdir -p {{.+}}/nested
+CHECK-OUTPUT-NEXT: /usr/bin/sftp
+CHECK-OUTPUT-DAG: -get '{{.+}}-REMOTE/output/nested/output' '{{.+}}/nested/output'
+CHECK-OUTPUT-DAG: -get '{{.+}}-REMOTE/output/nested/input' '{{.+}}/nested/input'
diff --git a/test/remote-run/env.test-sh b/test/remote-run/env.test-sh
new file mode 100644
index 0000000..e207dc7
--- /dev/null
+++ b/test/remote-run/env.test-sh
@@ -0,0 +1,6 @@
+RUN: env REMOTE_RUN_CHILD_FOO=foo REMOTE_RUN_CHILD_BAR=bar %debug-remote-run sh -c 'echo ":${FOO}:" ":${BAR}:"' | %FileCheck %s
+RUN: env REMOTE_RUN_CHILD_FOO=foo REMOTE_RUN_CHILD_BAR=bar %debug-remote-run -v sh -c 'echo ":${FOO}:" ":${BAR}:"' 2>&1 >/dev/null | %FileCheck -check-prefix VERBOSE %s
+
+CHECK: {{^:foo: :bar:$}}
+
+VERBOSE: /usr/bin/env FOO=foo BAR=bar sh -c echo ":${FOO}:" ":${BAR}:"
diff --git a/test/remote-run/exit-code.test-sh b/test/remote-run/exit-code.test-sh
new file mode 100644
index 0000000..7545d60
--- /dev/null
+++ b/test/remote-run/exit-code.test-sh
@@ -0,0 +1,3 @@
+RUN: not %debug-remote-run false >%t.txt 2>%t.errs.txt
+RUN: test -f %t.txt -a ! -s %t.txt
+RUN: test -f %t.errs.txt -a ! -s %t.errs.txt
diff --git a/test/remote-run/identity.test-sh b/test/remote-run/identity.test-sh
new file mode 100644
index 0000000..ff68b62
--- /dev/null
+++ b/test/remote-run/identity.test-sh
@@ -0,0 +1,38 @@
+RUN: %utils/remote-run -n --remote-dir /xyz-REMOTE -i spiderman --output-prefix %t some_user@some_host:12345 cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck %s
+
+CHECK: /usr/bin/ssh -n
+CHECK-DAG: -p 12345
+CHECK-DAG: -i spiderman
+CHECK-SAME: some_user@some_host -- '/usr/bin/env' '/bin/mkdir' '-p' '{{.+}}-REMOTE/output/nested'
+
+CHECK-NEXT: /usr/bin/sftp
+CHECK-DAG: -P 12345
+CHECK-DAG: -i spiderman
+CHECK-SAME: some_user@some_host
+CHECK-DAG: -put '{{.+}}/nested/output' '/xyz-REMOTE/output/nested/output'
+CHECK-DAG: -put '{{.+}}/nested/input' '/xyz-REMOTE/output/nested/input'
+
+CHECK: /usr/bin/ssh -n
+CHECK-DAG: -p 12345
+CHECK-DAG: -i spiderman
+CHECK-SAME: some_user@some_host -- '/usr/bin/env' 'cp'
+
+CHECK-NEXT: {{^}}/bin/mkdir -p {{.+}}/nested
+
+CHECK-NEXT: /usr/bin/sftp
+CHECK-DAG: -P 12345
+CHECK-DAG: -i spiderman
+CHECK-SAME: some_user@some_host
+CHECK-DAG: -get '/xyz-REMOTE/output/nested/output' '{{.+}}/nested/output'
+CHECK-DAG: -get '/xyz-REMOTE/output/nested/input' '{{.+}}/nested/input'
+
+# Make sure things work without a port.
+RUN: %utils/remote-run -n --remote-dir /xyz-REMOTE -i spiderman --output-prefix %t some_user@some_host cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck -check-prefix CHECK-PORTLESS %s
+
+CHECK-PORTLESS: /usr/bin/sftp
+CHECK-PORTLESS-SAME: -i spiderman
+CHECK-PORTLESS-SAME: some_user@some_host
+
+CHECK-PORTLESS: /usr/bin/ssh -n
+CHECK-PORTLESS-SAME: -i spiderman
+CHECK-PORTLESS-SAME: some_user@some_host -- '/usr/bin/env' 'cp'
diff --git a/test/remote-run/lit.local.cfg b/test/remote-run/lit.local.cfg
new file mode 100644
index 0000000..afc3094
--- /dev/null
+++ b/test/remote-run/lit.local.cfg
@@ -0,0 +1,5 @@
+# Make a local copy of the substitutions.
+config.substitutions = list(config.substitutions)
+
+config.substitutions.insert(0, ('%debug-remote-run',
+  '%utils/remote-run --debug-as-local --remote-dir %t-REMOTE') )
diff --git a/test/remote-run/port.test-sh b/test/remote-run/port.test-sh
new file mode 100644
index 0000000..2e6ebd2
--- /dev/null
+++ b/test/remote-run/port.test-sh
@@ -0,0 +1,15 @@
+RUN: %utils/remote-run -n --remote-dir /xyz-REMOTE --output-prefix %t some_user@some_host:12345 cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck %s
+
+CHECK: /usr/bin/ssh -n -p 12345 some_user@some_host -- '/usr/bin/env' '/bin/mkdir' '-p' '{{.+}}-REMOTE/output/nested'
+CHECK-NEXT: /usr/bin/sftp
+CHECK-SAME: -P 12345
+CHECK-SAME: some_user@some_host
+CHECK-DAG: -put '{{.+}}/nested/output' '/xyz-REMOTE/output/nested/output'
+CHECK-DAG: -put '{{.+}}/nested/input' '/xyz-REMOTE/output/nested/input'
+CHECK: /usr/bin/ssh -n -p 12345 some_user@some_host -- '/usr/bin/env' 'cp'
+CHECK-NEXT: {{^}}/bin/mkdir -p {{.+}}/nested
+CHECK-NEXT: /usr/bin/sftp
+CHECK-SAME: -P 12345
+CHECK-SAME: some_user@some_host
+CHECK-DAG: -get '/xyz-REMOTE/output/nested/output' '{{.+}}/nested/output'
+CHECK-DAG: -get '/xyz-REMOTE/output/nested/input' '{{.+}}/nested/input'
diff --git a/test/remote-run/run-only.test-sh b/test/remote-run/run-only.test-sh
new file mode 100644
index 0000000..db7186d
--- /dev/null
+++ b/test/remote-run/run-only.test-sh
@@ -0,0 +1,6 @@
+RUN: %debug-remote-run echo hello | %FileCheck %s
+RUN: %debug-remote-run -v echo hello 2>&1 >/dev/null | %FileCheck -check-prefix VERBOSE %s
+
+CHECK: {{^hello$}}
+
+VERBOSE: /usr/bin/env echo hello
diff --git a/test/remote-run/stderr.test-sh b/test/remote-run/stderr.test-sh
new file mode 100644
index 0000000..d18e5fa
--- /dev/null
+++ b/test/remote-run/stderr.test-sh
@@ -0,0 +1,15 @@
+RUN: %debug-remote-run sh -c "echo hello; echo goodbye >&2" > %t.stdout.txt 2> %t.stderr.txt
+RUN: %FileCheck -check-prefix CHECK-STDOUT %s < %t.stdout.txt
+RUN: %FileCheck -check-prefix CHECK-STDERR %s < %t.stderr.txt
+
+RUN: not %debug-remote-run sh -c "echo hello; echo goodbye >&2; false" > %t.stdout.txt 2> %t.stderr.txt
+RUN: %FileCheck -check-prefix CHECK-STDOUT %s < %t.stdout.txt
+RUN: %FileCheck -check-prefix CHECK-STDERR %s < %t.stderr.txt
+
+CHECK-STDOUT-NOT: goodbye
+CHECK-STDOUT: {{^hello$}}
+CHECK-STDOUT-NOT: goodbye
+
+CHECK-STDERR-NOT: hello
+CHECK-STDERR: {{^goodbye$}}
+CHECK-STDERR-NOT: hello
diff --git a/test/remote-run/upload-and-download.test-sh b/test/remote-run/upload-and-download.test-sh
new file mode 100644
index 0000000..0dc3c68
--- /dev/null
+++ b/test/remote-run/upload-and-download.test-sh
@@ -0,0 +1,54 @@
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t-REMOTE)
+RUN: touch %t/input %t/BAD
+RUN: %debug-remote-run --output-prefix %t cp %t/input %t/output
+RUN: ls %t/ | %FileCheck %s
+RUN: ls %t-REMOTE/output/ | %FileCheck -check-prefix CHECK-REMOTE %s
+
+CHECK: BAD
+CHECK-NEXT: {{^input$}}
+CHECK-NEXT: {{^output$}}
+
+CHECK-REMOTE-NOT: BAD
+CHECK-REMOTE: {{^input$}}
+CHECK-REMOTE-NEXT: {{^output$}}
+CHECK-REMOTE-NOT: BAD
+
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t/nested)
+RUN: %empty-directory(%t-REMOTE)
+RUN: touch %t/nested/input %t/nested/BAD
+RUN: %debug-remote-run --output-prefix %t cp %t/nested/input %t/nested/output
+RUN: ls %t/nested/ | %FileCheck %s
+RUN: ls %t-REMOTE/output/nested/ | %FileCheck -check-prefix CHECK-REMOTE %s
+
+RUN: %debug-remote-run -v --output-prefix %t cp %t/nested/input %t/nested/output 2>&1 >/dev/null | %FileCheck -check-prefix VERBOSE %s
+
+VERBOSE: /usr/bin/env /bin/mkdir -p {{.+}}-REMOTE/output/nested
+VERBOSE-NEXT: /usr/bin/sftp
+VERBOSE-DAG: -put '{{.+}}/nested/output' '{{.+}}-REMOTE/output/nested/output'
+VERBOSE-DAG: -put '{{.+}}/nested/input' '{{.+}}-REMOTE/output/nested/input'
+VERBOSE: /usr/bin/env cp
+VERBOSE-NEXT: {{^}}/bin/mkdir -p {{.+}}/nested
+VERBOSE-NEXT: /usr/bin/sftp
+VERBOSE-DAG: -get '{{.+}}-REMOTE/output/nested/output' '{{.+}}/nested/output'
+VERBOSE-DAG: -get '{{.+}}-REMOTE/output/nested/input' '{{.+}}/nested/input'
+
+RUN: %empty-directory(%t)
+RUN: touch %t/xyz-1before
+RUN: %debug-remote-run --output-prefix %t/xyz cp %t/xyz-1before %t/xyz-2after
+RUN: ls %t | %FileCheck -check-prefix CHECK-PREFIXED %s
+RUN: ls %t-REMOTE/ | %FileCheck -check-prefix CHECK-PREFIXED-REMOTE %s
+
+CHECK-PREFIXED: {{^xyz-1before$}}
+CHECK-PREFIXED: {{^xyz-2after$}}
+
+CHECK-PREFIXED-REMOTE: {{^output-1before$}}
+CHECK-PREFIXED-REMOTE: {{^output-2after$}}
+
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t-REMOTE)
+RUN: touch %t/input %t/BAD
+RUN: %debug-remote-run --output-prefix %t --remote-output-prefix custom-output cp %t/input %t/output
+RUN: ls %t/ | %FileCheck %s
+RUN: ls %t-REMOTE/custom-output/ | %FileCheck -check-prefix CHECK-REMOTE %s
diff --git a/test/remote-run/upload-stderr.test-sh b/test/remote-run/upload-stderr.test-sh
new file mode 100644
index 0000000..bd0bb5d
--- /dev/null
+++ b/test/remote-run/upload-stderr.test-sh
@@ -0,0 +1,6 @@
+RUN: %empty-directory(%t)
+RUN: %empty-directory(%t/REMOTE/input)
+RUN: chmod a-w %t/REMOTE/input
+RUN: %debug-remote-run --remote-dir %t/REMOTE --input-prefix %S/Inputs/upload/ true -- %S/Inputs/upload/1.txt 2>&1 | %FileCheck %s
+
+CHECK: Permission denied
diff --git a/test/remote-run/upload.test-sh b/test/remote-run/upload.test-sh
new file mode 100644
index 0000000..9e8397c
--- /dev/null
+++ b/test/remote-run/upload.test-sh
@@ -0,0 +1,37 @@
+RUN: %debug-remote-run --input-prefix %S/Inputs/upload/ ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt | %FileCheck -check-prefix CHECK-REMOTE %s
+RUN: ls %t-REMOTE/input/ | %FileCheck %s
+
+RUN: %empty-directory(%t-REMOTE)
+RUN: %debug-remote-run --input-prefix %S/Inputs/ ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt | %FileCheck -check-prefix CHECK-REMOTE-NESTED %s
+RUN: ls %t-REMOTE/input/upload/ | %FileCheck %s
+RUN: %debug-remote-run -v --input-prefix %S/Inputs/ ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt 2>&1 >/dev/null | %FileCheck -check-prefix VERBOSE-NESTED %s
+
+RUN: %empty-directory(%t-REMOTE)
+RUN: %debug-remote-run --input-prefix %S/Inputs/upload/1 ls %S/Inputs/upload/1.txt | %FileCheck -check-prefix CHECK-REMOTE-SINGLE-FILE %s
+RUN: test -f %t-REMOTE/input.txt
+
+RUN: %empty-directory(%t-REMOTE)
+RUN: %debug-remote-run --input-prefix %S/Inputs/upload/ --remote-input-prefix custom-input ls %S/Inputs/upload/1.txt %S/Inputs/upload/2.txt | %FileCheck -check-prefix CHECK-REMOTE-CUSTOM %s
+RUN: ls %t-REMOTE/custom-input/ | %FileCheck %s
+
+CHECK-REMOTE: {{-REMOTE/input/1.txt$}}
+CHECK-REMOTE-NEXT: {{-REMOTE/input/2.txt$}}
+
+CHECK-REMOTE-NESTED: {{-REMOTE/input/upload/1.txt$}}
+CHECK-REMOTE-NESTED-NEXT: {{-REMOTE/input/upload/2.txt$}}
+
+CHECK-REMOTE-SINGLE-FILE: {{-REMOTE/input.txt$}}
+
+CHECK-REMOTE-CUSTOM: {{-REMOTE/custom-input/1.txt$}}
+CHECK-REMOTE-CUSTOM-NEXT: {{-REMOTE/custom-input/2.txt$}}
+
+CHECK-NOT: BAD
+CHECK: {{^1.txt$}}
+CHECK-NEXT: {{^2.txt$}}
+CHECK-NOT: BAD
+
+VERBOSE-NESTED: /usr/bin/env /bin/mkdir -p {{.+}}-REMOTE/input/upload
+VERBOSE-NESTED-NEXT: /usr/bin/sftp
+VERBOSE-NESTED-DAG: -put '{{.+}}/Inputs/upload/1.txt' '{{.+}}-REMOTE/input/upload/1.txt'
+VERBOSE-NESTED-DAG: -put '{{.+}}/Inputs/upload/2.txt' '{{.+}}-REMOTE/input/upload/2.txt'
+VERBOSE-NESTED: /usr/bin/env ls
diff --git a/tools/SourceKit/tools/swift-lang/CMakeLists.txt b/tools/SourceKit/tools/swift-lang/CMakeLists.txt
index bd7e3d6..5d92c12 100644
--- a/tools/SourceKit/tools/swift-lang/CMakeLists.txt
+++ b/tools/SourceKit/tools/swift-lang/CMakeLists.txt
@@ -2,10 +2,12 @@
   set(EXTRA_COMPILE_FLAGS "-I" "${SOURCEKITD_SOURCE_DIR}/include/sourcekitd")
   set(SOURCEKITD_LINK_LIBS sourcekitdInProc)
   set(INSTALLED_COMP sourcekit-inproc)
+  set(DEPENDS_LIST "sourcekitd-test" "sourcekitdInProc")
 else()
   set(EXTRA_COMPILE_FLAGS "-F" "${SWIFT_LIBRARY_OUTPUT_INTDIR}")
   set(SOURCEKITD_LINK_LIBS sourcekitd)
   set(INSTALLED_COMP sourcekit-xpc-service)
+  set(DEPENDS_LIST "sourcekitd-test")
 endif()
 
 add_swift_library(swiftSwiftLang SHARED
@@ -16,7 +18,7 @@
   SourceKitdUID.swift
   UIDs.swift.gyb
 
-  DEPENDS sourcekitd-test
+  DEPENDS ${DEPENDS_LIST}
   PRIVATE_LINK_LIBRARIES ${SOURCEKITD_LINK_LIBS}
   SWIFT_COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS}
   INSTALL_IN_COMPONENT ${INSTALLED_COMP}
diff --git a/tools/SwiftSyntax/AbsolutePosition.swift b/tools/SwiftSyntax/AbsolutePosition.swift
index 7b0f265..518a4b0 100644
--- a/tools/SwiftSyntax/AbsolutePosition.swift
+++ b/tools/SwiftSyntax/AbsolutePosition.swift
@@ -12,7 +12,7 @@
 
 /// An absolute position in a source file as text - the absolute utf8Offset from
 /// the start, line, and column.
-public final class AbsolutePosition {
+public struct AbsolutePosition {
   public let utf8Offset: Int
   public let line: Int
   public let column: Int
diff --git a/tools/SwiftSyntax/SyntaxData.swift b/tools/SwiftSyntax/SyntaxData.swift
index 916d5f0..920b1c9 100644
--- a/tools/SwiftSyntax/SyntaxData.swift
+++ b/tools/SwiftSyntax/SyntaxData.swift
@@ -18,6 +18,15 @@
 /// exposed to clients.
 typealias NodeIdentifier = [Int]
 
+/// Box a value type into a reference type
+fileprivate class Box<T> {
+  let value: T
+
+  init(_ value: T) {
+    self.value = value
+  }
+}
+
 /// SyntaxData is the underlying storage for each Syntax node.
 /// It's modelled as an array that stores and caches a SyntaxData for each raw
 /// syntax node in its layout. It is up to the specific Syntax nodes to maintain
@@ -38,7 +47,7 @@
 
   let childCaches: [AtomicCache<SyntaxData>]
 
-  let positionCache: AtomicCache<AbsolutePosition>
+  private let positionCache: AtomicCache<Box<AbsolutePosition>>
 
   fileprivate func calculatePosition() -> AbsolutePosition {
     guard let parent = parent else {
@@ -62,7 +71,7 @@
 
   /// The position of the start of this node's leading trivia
   var position: AbsolutePosition {
-    return positionCache.value { return calculatePosition() }
+    return positionCache.value({ return Box(calculatePosition()) }).value
   }
 
   /// The position of the start of this node's content, skipping its trivia
@@ -93,7 +102,7 @@
     self.indexInParent = indexInParent
     self.parent = parent
     self.childCaches = raw.layout.map { _ in AtomicCache<SyntaxData>() }
-    self.positionCache = AtomicCache<AbsolutePosition>()
+    self.positionCache = AtomicCache<Box<AbsolutePosition>>()
   }
 
   /// The index path from this node to the root. This can be used to uniquely
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 1a747a6..e4be297 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -123,6 +123,9 @@
 Verbose("v", llvm::cl::desc("Verbose"));
 
 static llvm::cl::opt<bool>
+Abi("abi", llvm::cl::desc("Dumping ABI interface"),  llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
 PrintModule("print-module", llvm::cl::desc("Print module names in diagnostics"));
 
 static llvm::cl::opt<ActionType>
@@ -250,6 +253,7 @@
 };
 
 class SDKContext {
+  bool ABI;
   llvm::StringSet<> TextData;
   llvm::BumpPtrAllocator Allocator;
   UpdatedNodesMap UpdateMap;
@@ -257,6 +261,7 @@
   NodeMap RevertTypeAliasUpdateMap;
   TypeMemberDiffVector TypeMemberDiffs;
 public:
+  SDKContext(bool ABI): ABI(ABI) {}
   llvm::BumpPtrAllocator &allocator() {
     return Allocator;
   }
@@ -275,6 +280,7 @@
   TypeMemberDiffVector &getTypeMemberDiffs() {
     return TypeMemberDiffs;
   }
+  bool checkingABI() const { return ABI; }
 };
 
 // A node matcher will traverse two trees of SDKNode and find matched nodes
@@ -1341,6 +1347,18 @@
   return ReferenceOwnership::Strong;
 }
 
+// Get a requirement with all types canonicalized.
+Requirement getCanonicalRequirement(Requirement &Req) {
+  auto kind = Req.getKind();
+  if (kind == RequirementKind::Layout) {
+    return Requirement(kind, Req.getFirstType()->getCanonicalType(),
+                       Req.getLayoutConstraint());
+  } else {
+    return Requirement(kind, Req.getFirstType()->getCanonicalType(),
+                       Req.getSecondType()->getCanonicalType());
+  }
+}
+
 static StringRef printGenericSignature(SDKContext &Ctx, ValueDecl *VD) {
   llvm::SmallString<32> Result;
   llvm::raw_svector_ostream OS(Result);
@@ -1355,7 +1373,10 @@
       } else {
         First = false;
       }
-      Req.print(OS, PrintOptions::printInterface());
+      if (Ctx.checkingABI())
+        getCanonicalRequirement(Req).print(OS, PrintOptions::printInterface());
+      else
+        Req.print(OS, PrintOptions::printInterface());
     }
     OS << ">";
     return Ctx.buffer(OS.str());
@@ -1363,7 +1384,10 @@
 
   if (auto *GC = VD->getAsGenericContext()) {
     if (auto *Sig = GC->getGenericSignature()) {
-      Sig->print(OS);
+      if (Ctx.checkingABI())
+        Sig->getCanonicalSignature()->print(OS);
+      else
+        Sig->print(OS);
       return Ctx.buffer(OS.str());
     }
   }
@@ -1438,6 +1462,9 @@
 // representing the return value type of a function decl.
 static SDKNode *constructTypeNode(SDKContext &Ctx, Type T,
                                   TypeInitInfo InitInfo = TypeInitInfo()) {
+  if (Ctx.checkingABI()) {
+    T = T->getCanonicalType();
+  }
   SDKNode* Root = SDKNodeInitInfo(Ctx, T, InitInfo)
     .createSDKNode(SDKNodeKind::TypeNominal);
 
@@ -3814,7 +3841,7 @@
     llvm::errs() << RightPath << " does not exist\n";
     return 1;
   }
-  SDKContext Ctx;
+  SDKContext Ctx(options::Abi);
   SwiftDeclCollector LeftCollector(Ctx);
   LeftCollector.deSerialize(LeftPath);
   SwiftDeclCollector RightCollector(Ctx);
@@ -3866,7 +3893,7 @@
     return 1;
   }
   llvm::errs() << "Diffing: " << LeftPath << " and " << RightPath << "\n";
-  SDKContext Ctx;
+  SDKContext Ctx(options::Abi);
   SwiftDeclCollector LeftCollector(Ctx);
   LeftCollector.deSerialize(LeftPath);
   SwiftDeclCollector RightCollector(Ctx);
@@ -3990,7 +4017,7 @@
     Modules.push_back(M);
   }
 
-  SDKContext Ctx;
+  SDKContext Ctx(options::Abi);
   for (auto M : Modules) {
     SwiftDeclCollector Collector(Ctx);
     SmallVector<Decl*, 256> Decls;
@@ -4047,7 +4074,7 @@
   }
   if (options::Verbose)
     llvm::errs() << "Scanning symbols...\n";
-  SDKContext SDKCtx;
+  SDKContext SDKCtx(options::Abi);
   SwiftDeclCollector Collector(SDKCtx);
   Collector.lookupVisibleDecls(Modules);
   if (options::Verbose)
@@ -4202,7 +4229,7 @@
     llvm::errs() << dumpPath << " does not exist\n";
     return 1;
   }
-  SDKContext Ctx;
+  SDKContext Ctx(options::Abi);
   SwiftDeclCollector Collector(Ctx);
   Collector.deSerialize(dumpPath);
   Collector.serialize(OutputPath);
@@ -4215,7 +4242,7 @@
     llvm::errs() << dumpPath << " does not exist\n";
     return 1;
   }
-  SDKContext Ctx;
+  SDKContext Ctx(options::Abi);
   SwiftDeclCollector Collector(Ctx);
   Collector.deSerialize(dumpPath);
   struct FinderByLocation: SDKNodeVisitor {
diff --git a/unittests/Basic/OwnedStringTest.cpp b/unittests/Basic/OwnedStringTest.cpp
index c86fd9d..25ac1a6 100644
--- a/unittests/Basic/OwnedStringTest.cpp
+++ b/unittests/Basic/OwnedStringTest.cpp
@@ -18,177 +18,43 @@
 TEST(OwnedStringTest, char_pointer_empty) {
   const char *data = "";
   const size_t length = strlen(data);
-  OwnedString ownedString(data);
+  OwnedString ownedString = OwnedString::makeUnowned(data);
 
   EXPECT_EQ(length, ownedString.size());
   EXPECT_TRUE(ownedString.empty());
-
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_TRUE(copy.empty());
-
-  StringRef str = copy.str();
-  EXPECT_EQ("", str);
-  EXPECT_EQ(length, str.size());
+  EXPECT_EQ(data, ownedString.str().data());
 }
 
 TEST(OwnedStringTest, char_pointer_non_empty) {
   const char *data = "string";
   const size_t length = strlen(data);
-  OwnedString ownedString(data);
+  OwnedString ownedString = OwnedString::makeUnowned(data);
 
   EXPECT_EQ(length, ownedString.size());
   EXPECT_FALSE(ownedString.empty());
-
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
-
-  StringRef str = copy.str();
-  EXPECT_EQ("string", str);
-  EXPECT_EQ(length, strlen(str.data()));
+  EXPECT_EQ(data, ownedString.str().data());
 }
 
-TEST(OwnedStringTest, char_pointer_length_equal) {
-  const char *data = "string";
+TEST(OwnedStringTest, ref_counted_copies_buffer) {
+  char *data = static_cast<char *>(malloc(6));
+  memcpy(data, "hello", 6);
   size_t length = strlen(data);
-  OwnedString ownedString(data, length);
 
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_FALSE(ownedString.empty());
+  OwnedString ownedString =
+      OwnedString::makeRefCounted(StringRef(data, length));
 
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
+  EXPECT_EQ(ownedString.str(), "hello");
+  EXPECT_NE(ownedString.str().data(), data);
 
-  // Make sure we correctly copied the data and that it is null
-  // terminated.
-  StringRef str = copy.str();
-  EXPECT_EQ("string", str);
-  EXPECT_EQ(length, strlen(str.data()));
+  memcpy(data, "world", 6);
+
+  // Even if the original buffer changes, the string should stay the same
+  EXPECT_EQ(ownedString.str(), "hello");
 }
 
-TEST(OwnedStringTest, char_pointer_length_nonzero) {
-  const char *data = "string";
-  const size_t length = 1;
-  OwnedString ownedString(data, length);
+TEST(OwnedStringTest, ref_counted_assignment) {
+  OwnedString str = OwnedString::makeRefCounted("hello");
+  OwnedString copy = str;
 
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_FALSE(ownedString.empty());
-
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
-
-  // Make sure we correctly copied the data and that it is null
-  // terminated.
-  StringRef str = copy.str();
-  EXPECT_EQ("s", str);
-  EXPECT_EQ(1UL, strlen(str.data()));
-}
-
-TEST(OwnedStringTest, char_pointer_length_zero) {
-  const char *data = "string";
-  const size_t length = 0;
-  OwnedString ownedString(data, length);
-
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_TRUE(ownedString.empty());
-
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_TRUE(copy.empty());
-}
-
-TEST(OwnedStringTest, copy_original_new_different) {
-  // Initialize a mutable string.
-  const char *original = "string";
-  const size_t length = strlen(original);
-  char *data = static_cast<char *>(malloc(length + 1));
-  memcpy(data, original, length);
-  data[length] = '\0';
-
-  // Create an OwnedString.
-  OwnedString ownedString(data, length);
-
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_FALSE(ownedString.empty());
-
-  // Copy the string
-  OwnedString copy = ownedString.copy();
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
-
-  // Make sure we correctly copied the data and that it is null
-  // terminated.
-  StringRef str = copy.str();
-  EXPECT_EQ("string", str);
-  EXPECT_EQ(length, strlen(str.data()));
-
-  // Make sure updating the original pointer doesn't affect the copy.
-  data[0] = 'a';
-
-  EXPECT_EQ("string", str);
-}
-
-TEST(OwnedStringTest, copy_constructor_original_not_copy) {
-  // Initialize a mutable string.
-  const char *original = "string";
-  const size_t length = strlen(original);
-  char *data = static_cast<char *>(malloc(length + 1));
-  memcpy(data, original, length);
-  data[length] = '\0';
-
-  // Create an OwnedString.
-  OwnedString ownedString(data, length);
-
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_FALSE(ownedString.empty());
-
-  // Copy the string
-  OwnedString copy = OwnedString(ownedString);
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
-
-  // Make sure we correctly copied the data and that it is null
-  // terminated.
-  StringRef str = copy.str();
-  EXPECT_EQ("string", str);
-  EXPECT_EQ(length, strlen(str.data()));
-
-  // Make sure updating the original pointer doesn't affect the copy.
-  data[0] = 'a';
-
-  EXPECT_EQ("string", str);
-}
-
-TEST(OwnedStringTest, copy_constructor_original_copy) {
-  // Initialize a mutable string.
-  const char *original = "string";
-  const size_t length = strlen(original);
-  char *data = static_cast<char *>(malloc(length + 1));
-  memcpy(data, original, length);
-  data[length] = '\0';
-
-  // Create an OwnedString.
-  OwnedString ownedString(data, length);
-
-  EXPECT_EQ(length, ownedString.size());
-  EXPECT_FALSE(ownedString.empty());
-
-  // Copy the string
-  OwnedString copy = OwnedString(ownedString.copy());
-  EXPECT_EQ(length, copy.size());
-  EXPECT_FALSE(copy.empty());
-
-  // Make sure we correctly copied the data and that it is null
-  // terminated.
-  StringRef str = copy.str();
-  EXPECT_EQ("string", str);
-  EXPECT_EQ(length, strlen(str.data()));
-
-  // Make sure updating the original pointer doesn't affect the copy.
-  data[0] = 'a';
-
-  EXPECT_EQ("string", str);
+  EXPECT_EQ(str.str().data(), copy.str().data());
 }
diff --git a/utils/build-script-impl b/utils/build-script-impl
index ac1f644..cc285f7 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2823,7 +2823,7 @@
                 # Watchpoint testing is currently disabled: see rdar://38566150.
                 if [[ "$(true_false ${LLDB_TEST_SWIFT_ONLY})" == "TRUE" ]]; then
                     LLDB_TEST_SUBDIR_CLAUSE="--test-subdir lang/swift"
-                    LLDB_TEST_CATEGORIES="--skip-category=watchpoint --skip-category=dwo --skip-category=dsym --skip-category=gmodules -G swiftpr"
+                    LLDB_TEST_CATEGORIES="--skip-category=watchpoint --skip-category=dwo --skip-category=dsym --skip-category=gmodules"
                 else
                     LLDB_TEST_SUBDIR_CLAUSE=""
                     LLDB_TEST_CATEGORIES="--skip-category=watchpoint"
diff --git a/utils/gyb_syntax_support/__init__.py b/utils/gyb_syntax_support/__init__.py
index 06b0237..8711463 100644
--- a/utils/gyb_syntax_support/__init__.py
+++ b/utils/gyb_syntax_support/__init__.py
@@ -34,7 +34,9 @@
         token = child.main_token()
         tok_kind = token.kind if token else "unknown"
         tok_text = token.text if token else ""
-        return 'RawSyntax::missing(tok::%s, "%s")' % (tok_kind, tok_text)
+        return \
+            'RawSyntax::missing(tok::%s, OwnedString::makeUnowned("%s"))' % \
+            (tok_kind, tok_text)
     else:
         missing_kind = "Unknown" if child.syntax_kind == "Syntax" \
                        else child.syntax_kind
diff --git a/utils/remote-run b/utils/remote-run
new file mode 100755
index 0000000..5a9edf5
--- /dev/null
+++ b/utils/remote-run
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+# remote-run - Runs a command on another machine, for testing -----*- python -*-
+#
+# This source file is part of the Swift.org open source project
+#
+# Copyright (c) 2018 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 __future__ import print_function
+
+import argparse
+import os.path
+import subprocess
+import sys
+
+def quote(arg):
+    return repr(arg)
+
+class CommandRunner(object):
+    def __init__(self):
+        self.verbose = False
+        self.dry_run = False
+
+    @staticmethod
+    def _dirnames(files):
+        return list(set(os.path.dirname(f) for f in files))
+
+    def popen(self, command, **kwargs):
+        if self.verbose:
+            print(' '.join(command), file=sys.stderr)
+        if self.dry_run:
+            return None
+        return subprocess.Popen(command, **kwargs)
+
+    def send(self, local_to_remote_files):
+        # Prepare the remote directory structure.
+        # FIXME: This could be folded into the sftp connection below.
+        dirs_to_make = self._dirnames(local_to_remote_files.viewvalues())
+        self.run_remote(['/bin/mkdir', '-p'] + dirs_to_make)
+
+        # Send the local files.
+        sftp_commands = ("-put {0} {1}".format(quote(local_file), 
+                                               quote(remote_file))
+                         for local_file, remote_file
+                         in local_to_remote_files.viewitems())
+        self.run_sftp(sftp_commands)
+
+    def fetch(self, local_to_remote_files):
+        # Prepare the local directory structure.
+        dirs_to_make = self._dirnames(local_to_remote_files.viewkeys())
+        mkdir_command = ['/bin/mkdir', '-p'] + dirs_to_make
+        if self.verbose:
+            print(' '.join(mkdir_command), file=sys.stderr)
+        if not self.dry_run:
+            subprocess.check_call(mkdir_command)
+
+        # Fetch the remote files.
+        sftp_commands = ("-get {0} {1}".format(quote(remote_file), 
+                                               quote(local_file))
+                         for local_file, remote_file
+                         in local_to_remote_files.viewitems())
+        self.run_sftp(sftp_commands)
+
+    def run_remote(self, command, remote_env={}):
+        env_strings = ['{0}={1}'.format(k,v) for k,v in remote_env.viewitems()]
+        remote_invocation = self.remote_invocation(
+            ['/usr/bin/env'] + env_strings + command)
+        remote_proc = self.popen(remote_invocation, stdin=subprocess.PIPE,
+                                 stdout=None, stderr=None)
+        if self.dry_run:
+            return
+        _, _ = remote_proc.communicate()
+        if remote_proc.returncode:
+            # FIXME: We may still want to fetch the output files to see what
+            # went wrong.
+            sys.exit(remote_proc.returncode)
+    
+    def run_sftp(self, commands):
+        sftp_proc = self.popen(self.sftp_invocation(), stdin=subprocess.PIPE,
+                               stdout=subprocess.PIPE, stderr=None)
+        concatenated_commands = '\n'.join(commands)
+        if self.verbose:
+            print(concatenated_commands, file=sys.stderr)
+        if self.dry_run:
+            return
+        _, _ = sftp_proc.communicate(concatenated_commands)
+        if sftp_proc.returncode:
+            sys.exit(sftp_proc.returncode)
+
+class RemoteCommandRunner(CommandRunner):
+    def __init__(self, host, identity_path):
+        if ':' in host:
+            (self.remote_host, self.port) = host.rsplit(':', 1)
+        else:
+            self.remote_host = host
+            self.port = None
+        self.identity_path = identity_path
+
+    def common_options(self, port_flag):
+        port_option = [port_flag, self.port] if self.port else []
+        identity_option = (
+            ['-i', self.identity_path] if self.identity_path else [])
+        return port_option + identity_option
+
+    def remote_invocation(self, command):
+        return (['/usr/bin/ssh', '-n'] +
+                self.common_options(port_flag='-p') +
+                [self.remote_host, '--'] +
+                [quote(arg) for arg in command])
+
+    def sftp_invocation(self):
+        return (['/usr/bin/sftp', '-b', '-', '-q'] +
+                self.common_options(port_flag='-P') +
+                [self.remote_host])
+
+class LocalCommandRunner(CommandRunner):
+    def __init__(self):
+        self.cached_sftp_server_path = None
+
+    def sftp_server_path(self):
+        if not self.cached_sftp_server_path:
+            paths_to_try = ['/usr/libexec/sftp-server', '/usr/lib/sftp-server']
+            self.cached_sftp_server_path = next(
+                (path for path in paths_to_try if os.path.exists(path)),
+                paths_to_try[0])
+        return self.cached_sftp_server_path
+
+    def remote_invocation(self, command):
+        return command
+
+    def sftp_invocation(self):
+        return ['/usr/bin/sftp', '-b', '-', '-q', '-D', self.sftp_server_path()]
+
+def find_transfers(args, source_prefix, dest_prefix):
+    if source_prefix.endswith(os.path.sep):
+        source_prefix = source_prefix[:-len(os.path.sep)]
+    return dict((arg, dest_prefix + arg[len(source_prefix):])
+                for arg in args if arg.startswith(source_prefix))
+
+def collect_remote_env(local_env=os.environ, prefix='REMOTE_RUN_CHILD_'):
+    return dict((key[len(prefix):], value)
+                for key, value in local_env.items() if key.startswith(prefix))
+
+def main():
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
+                        help='print commands as they are run')
+    parser.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
+                        help="print the commands that would have been run, but "
+                             "don't actually run them")
+
+    parser.add_argument('--remote-dir', required=True, metavar='PATH',
+                        help='(required) a writable temporary path on the '
+                             'remote machine')
+    parser.add_argument('--input-prefix',
+                        help='arguments matching this prefix will be uploaded')
+    parser.add_argument('--output-prefix',
+                        help='arguments matching this prefix will be both '
+                             'uploaded and downloaded')
+    parser.add_argument('--remote-input-prefix', default='input',
+                        help='input arguments use this prefix on the remote '
+                             'machine')
+    parser.add_argument('--remote-output-prefix', default='output',
+                        help='output arguments use this prefix on the remote '
+                             'machine')
+
+    parser.add_argument('-i', '--identity', dest='identity', metavar='FILE',
+                        help='an SSH identity file (private key) to use')
+    parser.add_argument('--debug-as-local', action='store_true',
+                        help='run commands locally instead of over SSH, for '
+                             'debugging purposes. The "host" argument is '
+                             'omitted.')
+
+    parser.add_argument('host',
+                        help='the host to connect to, in the form '
+                             '[user@]host[:port]')
+    parser.add_argument('command', nargs=argparse.REMAINDER,
+                        help='the command to run', metavar='command...')
+    args = parser.parse_args()
+
+    if args.debug_as_local:
+        runner = LocalCommandRunner()
+        args.command.insert(0, args.host)
+        del args.host
+    else:
+        runner = RemoteCommandRunner(args.host, args.identity)
+    runner.dry_run = args.dry_run
+    runner.verbose = args.verbose or args.dry_run
+
+    upload_files = dict()
+    download_files = dict()
+    if args.input_prefix:
+        remote_dir = os.path.join(args.remote_dir, args.remote_input_prefix)
+        input_files = find_transfers(args.command, args.input_prefix, 
+                                     remote_dir)
+        assert not any(upload_files.has_key(f) for f in input_files)
+        upload_files.update(input_files)
+    if args.output_prefix:
+        remote_dir = os.path.join(args.remote_dir, args.remote_output_prefix)
+        test_files = find_transfers(args.command, args.output_prefix, 
+                                    remote_dir)
+        assert not any(upload_files.has_key(f) for f in test_files)
+        upload_files.update(test_files)
+        assert not any(download_files.has_key(f) for f in test_files)
+        download_files.update(test_files)
+
+    if upload_files:
+        runner.send(upload_files)
+
+    remote_env = collect_remote_env()
+
+    translated_command = [upload_files.get(arg, download_files.get(arg, arg))
+                          for arg in args.command]
+    runner.run_remote(translated_command, remote_env)
+
+    if download_files:
+        runner.fetch(download_files)
+
+if __name__ == "__main__":
+    main()
diff --git a/validation-test/Driver/batch_mode_overlong_argv.swift b/validation-test/Driver/batch_mode_overlong_argv.swift
index bffbcfe..6d4412f 100644
--- a/validation-test/Driver/batch_mode_overlong_argv.swift
+++ b/validation-test/Driver/batch_mode_overlong_argv.swift
@@ -1,109 +1,109 @@
 // REQUIRES: OS=macosx
 // REQUIRES: no_asan
 // RUN: %empty-directory(%t)
-// RUN: touch  %t/f_1_1.swift %t/f_1_2.swift %t/f_1_3.swift %t/f_1_4.swift %t/f_1_5.swift %t/f_1_6.swift %t/f_1_7.swift %t/f_1_8.swift %t/f_1_9.swift %t/f_1_10.swift
-// RUN: touch  %t/f_2_1.swift %t/f_2_2.swift %t/f_2_3.swift %t/f_2_4.swift %t/f_2_5.swift %t/f_2_6.swift %t/f_2_7.swift %t/f_2_8.swift %t/f_2_9.swift %t/f_2_10.swift
-// RUN: touch  %t/f_3_1.swift %t/f_3_2.swift %t/f_3_3.swift %t/f_3_4.swift %t/f_3_5.swift %t/f_3_6.swift %t/f_3_7.swift %t/f_3_8.swift %t/f_3_9.swift %t/f_3_10.swift
-// RUN: touch  %t/f_4_1.swift %t/f_4_2.swift %t/f_4_3.swift %t/f_4_4.swift %t/f_4_5.swift %t/f_4_6.swift %t/f_4_7.swift %t/f_4_8.swift %t/f_4_9.swift %t/f_4_10.swift
-// RUN: touch  %t/f_5_1.swift %t/f_5_2.swift %t/f_5_3.swift %t/f_5_4.swift %t/f_5_5.swift %t/f_5_6.swift %t/f_5_7.swift %t/f_5_8.swift %t/f_5_9.swift %t/f_5_10.swift
-// RUN: touch  %t/f_6_1.swift %t/f_6_2.swift %t/f_6_3.swift %t/f_6_4.swift %t/f_6_5.swift %t/f_6_6.swift %t/f_6_7.swift %t/f_6_8.swift %t/f_6_9.swift %t/f_6_10.swift
-// RUN: touch  %t/f_7_1.swift %t/f_7_2.swift %t/f_7_3.swift %t/f_7_4.swift %t/f_7_5.swift %t/f_7_6.swift %t/f_7_7.swift %t/f_7_8.swift %t/f_7_9.swift %t/f_7_10.swift
-// RUN: touch  %t/f_8_1.swift %t/f_8_2.swift %t/f_8_3.swift %t/f_8_4.swift %t/f_8_5.swift %t/f_8_6.swift %t/f_8_7.swift %t/f_8_8.swift %t/f_8_9.swift %t/f_8_10.swift
-// RUN: touch  %t/f_9_1.swift %t/f_9_2.swift %t/f_9_3.swift %t/f_9_4.swift %t/f_9_5.swift %t/f_9_6.swift %t/f_9_7.swift %t/f_9_8.swift %t/f_9_9.swift %t/f_9_10.swift
-// RUN: touch  %t/f_10_1.swift %t/f_10_2.swift %t/f_10_3.swift %t/f_10_4.swift %t/f_10_5.swift %t/f_10_6.swift %t/f_10_7.swift %t/f_10_8.swift %t/f_10_9.swift %t/f_10_10.swift
-// RUN: touch  %t/f_11_1.swift %t/f_11_2.swift %t/f_11_3.swift %t/f_11_4.swift %t/f_11_5.swift %t/f_11_6.swift %t/f_11_7.swift %t/f_11_8.swift %t/f_11_9.swift %t/f_11_10.swift
-// RUN: touch  %t/f_12_1.swift %t/f_12_2.swift %t/f_12_3.swift %t/f_12_4.swift %t/f_12_5.swift %t/f_12_6.swift %t/f_12_7.swift %t/f_12_8.swift %t/f_12_9.swift %t/f_12_10.swift
-// RUN: touch  %t/f_13_1.swift %t/f_13_2.swift %t/f_13_3.swift %t/f_13_4.swift %t/f_13_5.swift %t/f_13_6.swift %t/f_13_7.swift %t/f_13_8.swift %t/f_13_9.swift %t/f_13_10.swift
-// RUN: touch  %t/f_14_1.swift %t/f_14_2.swift %t/f_14_3.swift %t/f_14_4.swift %t/f_14_5.swift %t/f_14_6.swift %t/f_14_7.swift %t/f_14_8.swift %t/f_14_9.swift %t/f_14_10.swift
-// RUN: touch  %t/f_15_1.swift %t/f_15_2.swift %t/f_15_3.swift %t/f_15_4.swift %t/f_15_5.swift %t/f_15_6.swift %t/f_15_7.swift %t/f_15_8.swift %t/f_15_9.swift %t/f_15_10.swift
-// RUN: touch  %t/f_16_1.swift %t/f_16_2.swift %t/f_16_3.swift %t/f_16_4.swift %t/f_16_5.swift %t/f_16_6.swift %t/f_16_7.swift %t/f_16_8.swift %t/f_16_9.swift %t/f_16_10.swift
-// RUN: touch  %t/f_17_1.swift %t/f_17_2.swift %t/f_17_3.swift %t/f_17_4.swift %t/f_17_5.swift %t/f_17_6.swift %t/f_17_7.swift %t/f_17_8.swift %t/f_17_9.swift %t/f_17_10.swift
-// RUN: touch  %t/f_18_1.swift %t/f_18_2.swift %t/f_18_3.swift %t/f_18_4.swift %t/f_18_5.swift %t/f_18_6.swift %t/f_18_7.swift %t/f_18_8.swift %t/f_18_9.swift %t/f_18_10.swift
-// RUN: touch  %t/f_19_1.swift %t/f_19_2.swift %t/f_19_3.swift %t/f_19_4.swift %t/f_19_5.swift %t/f_19_6.swift %t/f_19_7.swift %t/f_19_8.swift %t/f_19_9.swift %t/f_19_10.swift
-// RUN: touch  %t/f_20_1.swift %t/f_20_2.swift %t/f_20_3.swift %t/f_20_4.swift %t/f_20_5.swift %t/f_20_6.swift %t/f_20_7.swift %t/f_20_8.swift %t/f_20_9.swift %t/f_20_10.swift
-// RUN: touch  %t/f_21_1.swift %t/f_21_2.swift %t/f_21_3.swift %t/f_21_4.swift %t/f_21_5.swift %t/f_21_6.swift %t/f_21_7.swift %t/f_21_8.swift %t/f_21_9.swift %t/f_21_10.swift
-// RUN: touch  %t/f_22_1.swift %t/f_22_2.swift %t/f_22_3.swift %t/f_22_4.swift %t/f_22_5.swift %t/f_22_6.swift %t/f_22_7.swift %t/f_22_8.swift %t/f_22_9.swift %t/f_22_10.swift
-// RUN: touch  %t/f_23_1.swift %t/f_23_2.swift %t/f_23_3.swift %t/f_23_4.swift %t/f_23_5.swift %t/f_23_6.swift %t/f_23_7.swift %t/f_23_8.swift %t/f_23_9.swift %t/f_23_10.swift
-// RUN: touch  %t/f_24_1.swift %t/f_24_2.swift %t/f_24_3.swift %t/f_24_4.swift %t/f_24_5.swift %t/f_24_6.swift %t/f_24_7.swift %t/f_24_8.swift %t/f_24_9.swift %t/f_24_10.swift
-// RUN: touch  %t/f_25_1.swift %t/f_25_2.swift %t/f_25_3.swift %t/f_25_4.swift %t/f_25_5.swift %t/f_25_6.swift %t/f_25_7.swift %t/f_25_8.swift %t/f_25_9.swift %t/f_25_10.swift
-// RUN: touch  %t/f_26_1.swift %t/f_26_2.swift %t/f_26_3.swift %t/f_26_4.swift %t/f_26_5.swift %t/f_26_6.swift %t/f_26_7.swift %t/f_26_8.swift %t/f_26_9.swift %t/f_26_10.swift
-// RUN: touch  %t/f_27_1.swift %t/f_27_2.swift %t/f_27_3.swift %t/f_27_4.swift %t/f_27_5.swift %t/f_27_6.swift %t/f_27_7.swift %t/f_27_8.swift %t/f_27_9.swift %t/f_27_10.swift
-// RUN: touch  %t/f_28_1.swift %t/f_28_2.swift %t/f_28_3.swift %t/f_28_4.swift %t/f_28_5.swift %t/f_28_6.swift %t/f_28_7.swift %t/f_28_8.swift %t/f_28_9.swift %t/f_28_10.swift
-// RUN: touch  %t/f_29_1.swift %t/f_29_2.swift %t/f_29_3.swift %t/f_29_4.swift %t/f_29_5.swift %t/f_29_6.swift %t/f_29_7.swift %t/f_29_8.swift %t/f_29_9.swift %t/f_29_10.swift
-// RUN: touch  %t/f_30_1.swift %t/f_30_2.swift %t/f_30_3.swift %t/f_30_4.swift %t/f_30_5.swift %t/f_30_6.swift %t/f_30_7.swift %t/f_30_8.swift %t/f_30_9.swift %t/f_30_10.swift
-// RUN: touch  %t/f_31_1.swift %t/f_31_2.swift %t/f_31_3.swift %t/f_31_4.swift %t/f_31_5.swift %t/f_31_6.swift %t/f_31_7.swift %t/f_31_8.swift %t/f_31_9.swift %t/f_31_10.swift
-// RUN: touch  %t/f_32_1.swift %t/f_32_2.swift %t/f_32_3.swift %t/f_32_4.swift %t/f_32_5.swift %t/f_32_6.swift %t/f_32_7.swift %t/f_32_8.swift %t/f_32_9.swift %t/f_32_10.swift
-// RUN: touch  %t/f_33_1.swift %t/f_33_2.swift %t/f_33_3.swift %t/f_33_4.swift %t/f_33_5.swift %t/f_33_6.swift %t/f_33_7.swift %t/f_33_8.swift %t/f_33_9.swift %t/f_33_10.swift
-// RUN: touch  %t/f_34_1.swift %t/f_34_2.swift %t/f_34_3.swift %t/f_34_4.swift %t/f_34_5.swift %t/f_34_6.swift %t/f_34_7.swift %t/f_34_8.swift %t/f_34_9.swift %t/f_34_10.swift
-// RUN: touch  %t/f_35_1.swift %t/f_35_2.swift %t/f_35_3.swift %t/f_35_4.swift %t/f_35_5.swift %t/f_35_6.swift %t/f_35_7.swift %t/f_35_8.swift %t/f_35_9.swift %t/f_35_10.swift
-// RUN: touch  %t/f_36_1.swift %t/f_36_2.swift %t/f_36_3.swift %t/f_36_4.swift %t/f_36_5.swift %t/f_36_6.swift %t/f_36_7.swift %t/f_36_8.swift %t/f_36_9.swift %t/f_36_10.swift
-// RUN: touch  %t/f_37_1.swift %t/f_37_2.swift %t/f_37_3.swift %t/f_37_4.swift %t/f_37_5.swift %t/f_37_6.swift %t/f_37_7.swift %t/f_37_8.swift %t/f_37_9.swift %t/f_37_10.swift
-// RUN: touch  %t/f_38_1.swift %t/f_38_2.swift %t/f_38_3.swift %t/f_38_4.swift %t/f_38_5.swift %t/f_38_6.swift %t/f_38_7.swift %t/f_38_8.swift %t/f_38_9.swift %t/f_38_10.swift
-// RUN: touch  %t/f_39_1.swift %t/f_39_2.swift %t/f_39_3.swift %t/f_39_4.swift %t/f_39_5.swift %t/f_39_6.swift %t/f_39_7.swift %t/f_39_8.swift %t/f_39_9.swift %t/f_39_10.swift
-// RUN: touch  %t/f_40_1.swift %t/f_40_2.swift %t/f_40_3.swift %t/f_40_4.swift %t/f_40_5.swift %t/f_40_6.swift %t/f_40_7.swift %t/f_40_8.swift %t/f_40_9.swift %t/f_40_10.swift
-// RUN: touch  %t/f_41_1.swift %t/f_41_2.swift %t/f_41_3.swift %t/f_41_4.swift %t/f_41_5.swift %t/f_41_6.swift %t/f_41_7.swift %t/f_41_8.swift %t/f_41_9.swift %t/f_41_10.swift
-// RUN: touch  %t/f_42_1.swift %t/f_42_2.swift %t/f_42_3.swift %t/f_42_4.swift %t/f_42_5.swift %t/f_42_6.swift %t/f_42_7.swift %t/f_42_8.swift %t/f_42_9.swift %t/f_42_10.swift
-// RUN: touch  %t/f_43_1.swift %t/f_43_2.swift %t/f_43_3.swift %t/f_43_4.swift %t/f_43_5.swift %t/f_43_6.swift %t/f_43_7.swift %t/f_43_8.swift %t/f_43_9.swift %t/f_43_10.swift
-// RUN: touch  %t/f_44_1.swift %t/f_44_2.swift %t/f_44_3.swift %t/f_44_4.swift %t/f_44_5.swift %t/f_44_6.swift %t/f_44_7.swift %t/f_44_8.swift %t/f_44_9.swift %t/f_44_10.swift
-// RUN: touch  %t/f_45_1.swift %t/f_45_2.swift %t/f_45_3.swift %t/f_45_4.swift %t/f_45_5.swift %t/f_45_6.swift %t/f_45_7.swift %t/f_45_8.swift %t/f_45_9.swift %t/f_45_10.swift
-// RUN: touch  %t/f_46_1.swift %t/f_46_2.swift %t/f_46_3.swift %t/f_46_4.swift %t/f_46_5.swift %t/f_46_6.swift %t/f_46_7.swift %t/f_46_8.swift %t/f_46_9.swift %t/f_46_10.swift
-// RUN: touch  %t/f_47_1.swift %t/f_47_2.swift %t/f_47_3.swift %t/f_47_4.swift %t/f_47_5.swift %t/f_47_6.swift %t/f_47_7.swift %t/f_47_8.swift %t/f_47_9.swift %t/f_47_10.swift
-// RUN: touch  %t/f_48_1.swift %t/f_48_2.swift %t/f_48_3.swift %t/f_48_4.swift %t/f_48_5.swift %t/f_48_6.swift %t/f_48_7.swift %t/f_48_8.swift %t/f_48_9.swift %t/f_48_10.swift
-// RUN: touch  %t/f_49_1.swift %t/f_49_2.swift %t/f_49_3.swift %t/f_49_4.swift %t/f_49_5.swift %t/f_49_6.swift %t/f_49_7.swift %t/f_49_8.swift %t/f_49_9.swift %t/f_49_10.swift
-// RUN: touch  %t/f_50_1.swift %t/f_50_2.swift %t/f_50_3.swift %t/f_50_4.swift %t/f_50_5.swift %t/f_50_6.swift %t/f_50_7.swift %t/f_50_8.swift %t/f_50_9.swift %t/f_50_10.swift
-// RUN: touch  %t/f_51_1.swift %t/f_51_2.swift %t/f_51_3.swift %t/f_51_4.swift %t/f_51_5.swift %t/f_51_6.swift %t/f_51_7.swift %t/f_51_8.swift %t/f_51_9.swift %t/f_51_10.swift
-// RUN: touch  %t/f_52_1.swift %t/f_52_2.swift %t/f_52_3.swift %t/f_52_4.swift %t/f_52_5.swift %t/f_52_6.swift %t/f_52_7.swift %t/f_52_8.swift %t/f_52_9.swift %t/f_52_10.swift
-// RUN: touch  %t/f_53_1.swift %t/f_53_2.swift %t/f_53_3.swift %t/f_53_4.swift %t/f_53_5.swift %t/f_53_6.swift %t/f_53_7.swift %t/f_53_8.swift %t/f_53_9.swift %t/f_53_10.swift
-// RUN: touch  %t/f_54_1.swift %t/f_54_2.swift %t/f_54_3.swift %t/f_54_4.swift %t/f_54_5.swift %t/f_54_6.swift %t/f_54_7.swift %t/f_54_8.swift %t/f_54_9.swift %t/f_54_10.swift
-// RUN: touch  %t/f_55_1.swift %t/f_55_2.swift %t/f_55_3.swift %t/f_55_4.swift %t/f_55_5.swift %t/f_55_6.swift %t/f_55_7.swift %t/f_55_8.swift %t/f_55_9.swift %t/f_55_10.swift
-// RUN: touch  %t/f_56_1.swift %t/f_56_2.swift %t/f_56_3.swift %t/f_56_4.swift %t/f_56_5.swift %t/f_56_6.swift %t/f_56_7.swift %t/f_56_8.swift %t/f_56_9.swift %t/f_56_10.swift
-// RUN: touch  %t/f_57_1.swift %t/f_57_2.swift %t/f_57_3.swift %t/f_57_4.swift %t/f_57_5.swift %t/f_57_6.swift %t/f_57_7.swift %t/f_57_8.swift %t/f_57_9.swift %t/f_57_10.swift
-// RUN: touch  %t/f_58_1.swift %t/f_58_2.swift %t/f_58_3.swift %t/f_58_4.swift %t/f_58_5.swift %t/f_58_6.swift %t/f_58_7.swift %t/f_58_8.swift %t/f_58_9.swift %t/f_58_10.swift
-// RUN: touch  %t/f_59_1.swift %t/f_59_2.swift %t/f_59_3.swift %t/f_59_4.swift %t/f_59_5.swift %t/f_59_6.swift %t/f_59_7.swift %t/f_59_8.swift %t/f_59_9.swift %t/f_59_10.swift
-// RUN: touch  %t/f_60_1.swift %t/f_60_2.swift %t/f_60_3.swift %t/f_60_4.swift %t/f_60_5.swift %t/f_60_6.swift %t/f_60_7.swift %t/f_60_8.swift %t/f_60_9.swift %t/f_60_10.swift
-// RUN: touch  %t/f_61_1.swift %t/f_61_2.swift %t/f_61_3.swift %t/f_61_4.swift %t/f_61_5.swift %t/f_61_6.swift %t/f_61_7.swift %t/f_61_8.swift %t/f_61_9.swift %t/f_61_10.swift
-// RUN: touch  %t/f_62_1.swift %t/f_62_2.swift %t/f_62_3.swift %t/f_62_4.swift %t/f_62_5.swift %t/f_62_6.swift %t/f_62_7.swift %t/f_62_8.swift %t/f_62_9.swift %t/f_62_10.swift
-// RUN: touch  %t/f_63_1.swift %t/f_63_2.swift %t/f_63_3.swift %t/f_63_4.swift %t/f_63_5.swift %t/f_63_6.swift %t/f_63_7.swift %t/f_63_8.swift %t/f_63_9.swift %t/f_63_10.swift
-// RUN: touch  %t/f_64_1.swift %t/f_64_2.swift %t/f_64_3.swift %t/f_64_4.swift %t/f_64_5.swift %t/f_64_6.swift %t/f_64_7.swift %t/f_64_8.swift %t/f_64_9.swift %t/f_64_10.swift
-// RUN: touch  %t/f_65_1.swift %t/f_65_2.swift %t/f_65_3.swift %t/f_65_4.swift %t/f_65_5.swift %t/f_65_6.swift %t/f_65_7.swift %t/f_65_8.swift %t/f_65_9.swift %t/f_65_10.swift
-// RUN: touch  %t/f_66_1.swift %t/f_66_2.swift %t/f_66_3.swift %t/f_66_4.swift %t/f_66_5.swift %t/f_66_6.swift %t/f_66_7.swift %t/f_66_8.swift %t/f_66_9.swift %t/f_66_10.swift
-// RUN: touch  %t/f_67_1.swift %t/f_67_2.swift %t/f_67_3.swift %t/f_67_4.swift %t/f_67_5.swift %t/f_67_6.swift %t/f_67_7.swift %t/f_67_8.swift %t/f_67_9.swift %t/f_67_10.swift
-// RUN: touch  %t/f_68_1.swift %t/f_68_2.swift %t/f_68_3.swift %t/f_68_4.swift %t/f_68_5.swift %t/f_68_6.swift %t/f_68_7.swift %t/f_68_8.swift %t/f_68_9.swift %t/f_68_10.swift
-// RUN: touch  %t/f_69_1.swift %t/f_69_2.swift %t/f_69_3.swift %t/f_69_4.swift %t/f_69_5.swift %t/f_69_6.swift %t/f_69_7.swift %t/f_69_8.swift %t/f_69_9.swift %t/f_69_10.swift
-// RUN: touch  %t/f_70_1.swift %t/f_70_2.swift %t/f_70_3.swift %t/f_70_4.swift %t/f_70_5.swift %t/f_70_6.swift %t/f_70_7.swift %t/f_70_8.swift %t/f_70_9.swift %t/f_70_10.swift
-// RUN: touch  %t/f_71_1.swift %t/f_71_2.swift %t/f_71_3.swift %t/f_71_4.swift %t/f_71_5.swift %t/f_71_6.swift %t/f_71_7.swift %t/f_71_8.swift %t/f_71_9.swift %t/f_71_10.swift
-// RUN: touch  %t/f_72_1.swift %t/f_72_2.swift %t/f_72_3.swift %t/f_72_4.swift %t/f_72_5.swift %t/f_72_6.swift %t/f_72_7.swift %t/f_72_8.swift %t/f_72_9.swift %t/f_72_10.swift
-// RUN: touch  %t/f_73_1.swift %t/f_73_2.swift %t/f_73_3.swift %t/f_73_4.swift %t/f_73_5.swift %t/f_73_6.swift %t/f_73_7.swift %t/f_73_8.swift %t/f_73_9.swift %t/f_73_10.swift
-// RUN: touch  %t/f_74_1.swift %t/f_74_2.swift %t/f_74_3.swift %t/f_74_4.swift %t/f_74_5.swift %t/f_74_6.swift %t/f_74_7.swift %t/f_74_8.swift %t/f_74_9.swift %t/f_74_10.swift
-// RUN: touch  %t/f_75_1.swift %t/f_75_2.swift %t/f_75_3.swift %t/f_75_4.swift %t/f_75_5.swift %t/f_75_6.swift %t/f_75_7.swift %t/f_75_8.swift %t/f_75_9.swift %t/f_75_10.swift
-// RUN: touch  %t/f_76_1.swift %t/f_76_2.swift %t/f_76_3.swift %t/f_76_4.swift %t/f_76_5.swift %t/f_76_6.swift %t/f_76_7.swift %t/f_76_8.swift %t/f_76_9.swift %t/f_76_10.swift
-// RUN: touch  %t/f_77_1.swift %t/f_77_2.swift %t/f_77_3.swift %t/f_77_4.swift %t/f_77_5.swift %t/f_77_6.swift %t/f_77_7.swift %t/f_77_8.swift %t/f_77_9.swift %t/f_77_10.swift
-// RUN: touch  %t/f_78_1.swift %t/f_78_2.swift %t/f_78_3.swift %t/f_78_4.swift %t/f_78_5.swift %t/f_78_6.swift %t/f_78_7.swift %t/f_78_8.swift %t/f_78_9.swift %t/f_78_10.swift
-// RUN: touch  %t/f_79_1.swift %t/f_79_2.swift %t/f_79_3.swift %t/f_79_4.swift %t/f_79_5.swift %t/f_79_6.swift %t/f_79_7.swift %t/f_79_8.swift %t/f_79_9.swift %t/f_79_10.swift
-// RUN: touch  %t/f_80_1.swift %t/f_80_2.swift %t/f_80_3.swift %t/f_80_4.swift %t/f_80_5.swift %t/f_80_6.swift %t/f_80_7.swift %t/f_80_8.swift %t/f_80_9.swift %t/f_80_10.swift
-// RUN: touch  %t/f_81_1.swift %t/f_81_2.swift %t/f_81_3.swift %t/f_81_4.swift %t/f_81_5.swift %t/f_81_6.swift %t/f_81_7.swift %t/f_81_8.swift %t/f_81_9.swift %t/f_81_10.swift
-// RUN: touch  %t/f_82_1.swift %t/f_82_2.swift %t/f_82_3.swift %t/f_82_4.swift %t/f_82_5.swift %t/f_82_6.swift %t/f_82_7.swift %t/f_82_8.swift %t/f_82_9.swift %t/f_82_10.swift
-// RUN: touch  %t/f_83_1.swift %t/f_83_2.swift %t/f_83_3.swift %t/f_83_4.swift %t/f_83_5.swift %t/f_83_6.swift %t/f_83_7.swift %t/f_83_8.swift %t/f_83_9.swift %t/f_83_10.swift
-// RUN: touch  %t/f_84_1.swift %t/f_84_2.swift %t/f_84_3.swift %t/f_84_4.swift %t/f_84_5.swift %t/f_84_6.swift %t/f_84_7.swift %t/f_84_8.swift %t/f_84_9.swift %t/f_84_10.swift
-// RUN: touch  %t/f_85_1.swift %t/f_85_2.swift %t/f_85_3.swift %t/f_85_4.swift %t/f_85_5.swift %t/f_85_6.swift %t/f_85_7.swift %t/f_85_8.swift %t/f_85_9.swift %t/f_85_10.swift
-// RUN: touch  %t/f_86_1.swift %t/f_86_2.swift %t/f_86_3.swift %t/f_86_4.swift %t/f_86_5.swift %t/f_86_6.swift %t/f_86_7.swift %t/f_86_8.swift %t/f_86_9.swift %t/f_86_10.swift
-// RUN: touch  %t/f_87_1.swift %t/f_87_2.swift %t/f_87_3.swift %t/f_87_4.swift %t/f_87_5.swift %t/f_87_6.swift %t/f_87_7.swift %t/f_87_8.swift %t/f_87_9.swift %t/f_87_10.swift
-// RUN: touch  %t/f_88_1.swift %t/f_88_2.swift %t/f_88_3.swift %t/f_88_4.swift %t/f_88_5.swift %t/f_88_6.swift %t/f_88_7.swift %t/f_88_8.swift %t/f_88_9.swift %t/f_88_10.swift
-// RUN: touch  %t/f_89_1.swift %t/f_89_2.swift %t/f_89_3.swift %t/f_89_4.swift %t/f_89_5.swift %t/f_89_6.swift %t/f_89_7.swift %t/f_89_8.swift %t/f_89_9.swift %t/f_89_10.swift
-// RUN: touch  %t/f_90_1.swift %t/f_90_2.swift %t/f_90_3.swift %t/f_90_4.swift %t/f_90_5.swift %t/f_90_6.swift %t/f_90_7.swift %t/f_90_8.swift %t/f_90_9.swift %t/f_90_10.swift
-// RUN: touch  %t/f_91_1.swift %t/f_91_2.swift %t/f_91_3.swift %t/f_91_4.swift %t/f_91_5.swift %t/f_91_6.swift %t/f_91_7.swift %t/f_91_8.swift %t/f_91_9.swift %t/f_91_10.swift
-// RUN: touch  %t/f_92_1.swift %t/f_92_2.swift %t/f_92_3.swift %t/f_92_4.swift %t/f_92_5.swift %t/f_92_6.swift %t/f_92_7.swift %t/f_92_8.swift %t/f_92_9.swift %t/f_92_10.swift
-// RUN: touch  %t/f_93_1.swift %t/f_93_2.swift %t/f_93_3.swift %t/f_93_4.swift %t/f_93_5.swift %t/f_93_6.swift %t/f_93_7.swift %t/f_93_8.swift %t/f_93_9.swift %t/f_93_10.swift
-// RUN: touch  %t/f_94_1.swift %t/f_94_2.swift %t/f_94_3.swift %t/f_94_4.swift %t/f_94_5.swift %t/f_94_6.swift %t/f_94_7.swift %t/f_94_8.swift %t/f_94_9.swift %t/f_94_10.swift
-// RUN: touch  %t/f_95_1.swift %t/f_95_2.swift %t/f_95_3.swift %t/f_95_4.swift %t/f_95_5.swift %t/f_95_6.swift %t/f_95_7.swift %t/f_95_8.swift %t/f_95_9.swift %t/f_95_10.swift
-// RUN: touch  %t/f_96_1.swift %t/f_96_2.swift %t/f_96_3.swift %t/f_96_4.swift %t/f_96_5.swift %t/f_96_6.swift %t/f_96_7.swift %t/f_96_8.swift %t/f_96_9.swift %t/f_96_10.swift
-// RUN: touch  %t/f_97_1.swift %t/f_97_2.swift %t/f_97_3.swift %t/f_97_4.swift %t/f_97_5.swift %t/f_97_6.swift %t/f_97_7.swift %t/f_97_8.swift %t/f_97_9.swift %t/f_97_10.swift
-// RUN: touch  %t/f_98_1.swift %t/f_98_2.swift %t/f_98_3.swift %t/f_98_4.swift %t/f_98_5.swift %t/f_98_6.swift %t/f_98_7.swift %t/f_98_8.swift %t/f_98_9.swift %t/f_98_10.swift
-// RUN: touch  %t/f_99_1.swift %t/f_99_2.swift %t/f_99_3.swift %t/f_99_4.swift %t/f_99_5.swift %t/f_99_6.swift %t/f_99_7.swift %t/f_99_8.swift %t/f_99_9.swift %t/f_99_10.swift
-// RUN: touch  %t/f_100_1.swift %t/f_100_2.swift %t/f_100_3.swift %t/f_100_4.swift %t/f_100_5.swift %t/f_100_6.swift %t/f_100_7.swift %t/f_100_8.swift %t/f_100_9.swift %t/f_100_10.swift
-// RUN: mkdir -p %t/additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/
+// RUN: cd %t && touch ./f_1_1.swift ./f_1_2.swift ./f_1_3.swift ./f_1_4.swift ./f_1_5.swift ./f_1_6.swift ./f_1_7.swift ./f_1_8.swift ./f_1_9.swift ./f_1_10.swift
+// RUN: cd %t && touch ./f_2_1.swift ./f_2_2.swift ./f_2_3.swift ./f_2_4.swift ./f_2_5.swift ./f_2_6.swift ./f_2_7.swift ./f_2_8.swift ./f_2_9.swift ./f_2_10.swift
+// RUN: cd %t && touch ./f_3_1.swift ./f_3_2.swift ./f_3_3.swift ./f_3_4.swift ./f_3_5.swift ./f_3_6.swift ./f_3_7.swift ./f_3_8.swift ./f_3_9.swift ./f_3_10.swift
+// RUN: cd %t && touch ./f_4_1.swift ./f_4_2.swift ./f_4_3.swift ./f_4_4.swift ./f_4_5.swift ./f_4_6.swift ./f_4_7.swift ./f_4_8.swift ./f_4_9.swift ./f_4_10.swift
+// RUN: cd %t && touch ./f_5_1.swift ./f_5_2.swift ./f_5_3.swift ./f_5_4.swift ./f_5_5.swift ./f_5_6.swift ./f_5_7.swift ./f_5_8.swift ./f_5_9.swift ./f_5_10.swift
+// RUN: cd %t && touch ./f_6_1.swift ./f_6_2.swift ./f_6_3.swift ./f_6_4.swift ./f_6_5.swift ./f_6_6.swift ./f_6_7.swift ./f_6_8.swift ./f_6_9.swift ./f_6_10.swift
+// RUN: cd %t && touch ./f_7_1.swift ./f_7_2.swift ./f_7_3.swift ./f_7_4.swift ./f_7_5.swift ./f_7_6.swift ./f_7_7.swift ./f_7_8.swift ./f_7_9.swift ./f_7_10.swift
+// RUN: cd %t && touch ./f_8_1.swift ./f_8_2.swift ./f_8_3.swift ./f_8_4.swift ./f_8_5.swift ./f_8_6.swift ./f_8_7.swift ./f_8_8.swift ./f_8_9.swift ./f_8_10.swift
+// RUN: cd %t && touch ./f_9_1.swift ./f_9_2.swift ./f_9_3.swift ./f_9_4.swift ./f_9_5.swift ./f_9_6.swift ./f_9_7.swift ./f_9_8.swift ./f_9_9.swift ./f_9_10.swift
+// RUN: cd %t && touch ./f_10_1.swift ./f_10_2.swift ./f_10_3.swift ./f_10_4.swift ./f_10_5.swift ./f_10_6.swift ./f_10_7.swift ./f_10_8.swift ./f_10_9.swift ./f_10_10.swift
+// RUN: cd %t && touch ./f_11_1.swift ./f_11_2.swift ./f_11_3.swift ./f_11_4.swift ./f_11_5.swift ./f_11_6.swift ./f_11_7.swift ./f_11_8.swift ./f_11_9.swift ./f_11_10.swift
+// RUN: cd %t && touch ./f_12_1.swift ./f_12_2.swift ./f_12_3.swift ./f_12_4.swift ./f_12_5.swift ./f_12_6.swift ./f_12_7.swift ./f_12_8.swift ./f_12_9.swift ./f_12_10.swift
+// RUN: cd %t && touch ./f_13_1.swift ./f_13_2.swift ./f_13_3.swift ./f_13_4.swift ./f_13_5.swift ./f_13_6.swift ./f_13_7.swift ./f_13_8.swift ./f_13_9.swift ./f_13_10.swift
+// RUN: cd %t && touch ./f_14_1.swift ./f_14_2.swift ./f_14_3.swift ./f_14_4.swift ./f_14_5.swift ./f_14_6.swift ./f_14_7.swift ./f_14_8.swift ./f_14_9.swift ./f_14_10.swift
+// RUN: cd %t && touch ./f_15_1.swift ./f_15_2.swift ./f_15_3.swift ./f_15_4.swift ./f_15_5.swift ./f_15_6.swift ./f_15_7.swift ./f_15_8.swift ./f_15_9.swift ./f_15_10.swift
+// RUN: cd %t && touch ./f_16_1.swift ./f_16_2.swift ./f_16_3.swift ./f_16_4.swift ./f_16_5.swift ./f_16_6.swift ./f_16_7.swift ./f_16_8.swift ./f_16_9.swift ./f_16_10.swift
+// RUN: cd %t && touch ./f_17_1.swift ./f_17_2.swift ./f_17_3.swift ./f_17_4.swift ./f_17_5.swift ./f_17_6.swift ./f_17_7.swift ./f_17_8.swift ./f_17_9.swift ./f_17_10.swift
+// RUN: cd %t && touch ./f_18_1.swift ./f_18_2.swift ./f_18_3.swift ./f_18_4.swift ./f_18_5.swift ./f_18_6.swift ./f_18_7.swift ./f_18_8.swift ./f_18_9.swift ./f_18_10.swift
+// RUN: cd %t && touch ./f_19_1.swift ./f_19_2.swift ./f_19_3.swift ./f_19_4.swift ./f_19_5.swift ./f_19_6.swift ./f_19_7.swift ./f_19_8.swift ./f_19_9.swift ./f_19_10.swift
+// RUN: cd %t && touch ./f_20_1.swift ./f_20_2.swift ./f_20_3.swift ./f_20_4.swift ./f_20_5.swift ./f_20_6.swift ./f_20_7.swift ./f_20_8.swift ./f_20_9.swift ./f_20_10.swift
+// RUN: cd %t && touch ./f_21_1.swift ./f_21_2.swift ./f_21_3.swift ./f_21_4.swift ./f_21_5.swift ./f_21_6.swift ./f_21_7.swift ./f_21_8.swift ./f_21_9.swift ./f_21_10.swift
+// RUN: cd %t && touch ./f_22_1.swift ./f_22_2.swift ./f_22_3.swift ./f_22_4.swift ./f_22_5.swift ./f_22_6.swift ./f_22_7.swift ./f_22_8.swift ./f_22_9.swift ./f_22_10.swift
+// RUN: cd %t && touch ./f_23_1.swift ./f_23_2.swift ./f_23_3.swift ./f_23_4.swift ./f_23_5.swift ./f_23_6.swift ./f_23_7.swift ./f_23_8.swift ./f_23_9.swift ./f_23_10.swift
+// RUN: cd %t && touch ./f_24_1.swift ./f_24_2.swift ./f_24_3.swift ./f_24_4.swift ./f_24_5.swift ./f_24_6.swift ./f_24_7.swift ./f_24_8.swift ./f_24_9.swift ./f_24_10.swift
+// RUN: cd %t && touch ./f_25_1.swift ./f_25_2.swift ./f_25_3.swift ./f_25_4.swift ./f_25_5.swift ./f_25_6.swift ./f_25_7.swift ./f_25_8.swift ./f_25_9.swift ./f_25_10.swift
+// RUN: cd %t && touch ./f_26_1.swift ./f_26_2.swift ./f_26_3.swift ./f_26_4.swift ./f_26_5.swift ./f_26_6.swift ./f_26_7.swift ./f_26_8.swift ./f_26_9.swift ./f_26_10.swift
+// RUN: cd %t && touch ./f_27_1.swift ./f_27_2.swift ./f_27_3.swift ./f_27_4.swift ./f_27_5.swift ./f_27_6.swift ./f_27_7.swift ./f_27_8.swift ./f_27_9.swift ./f_27_10.swift
+// RUN: cd %t && touch ./f_28_1.swift ./f_28_2.swift ./f_28_3.swift ./f_28_4.swift ./f_28_5.swift ./f_28_6.swift ./f_28_7.swift ./f_28_8.swift ./f_28_9.swift ./f_28_10.swift
+// RUN: cd %t && touch ./f_29_1.swift ./f_29_2.swift ./f_29_3.swift ./f_29_4.swift ./f_29_5.swift ./f_29_6.swift ./f_29_7.swift ./f_29_8.swift ./f_29_9.swift ./f_29_10.swift
+// RUN: cd %t && touch ./f_30_1.swift ./f_30_2.swift ./f_30_3.swift ./f_30_4.swift ./f_30_5.swift ./f_30_6.swift ./f_30_7.swift ./f_30_8.swift ./f_30_9.swift ./f_30_10.swift
+// RUN: cd %t && touch ./f_31_1.swift ./f_31_2.swift ./f_31_3.swift ./f_31_4.swift ./f_31_5.swift ./f_31_6.swift ./f_31_7.swift ./f_31_8.swift ./f_31_9.swift ./f_31_10.swift
+// RUN: cd %t && touch ./f_32_1.swift ./f_32_2.swift ./f_32_3.swift ./f_32_4.swift ./f_32_5.swift ./f_32_6.swift ./f_32_7.swift ./f_32_8.swift ./f_32_9.swift ./f_32_10.swift
+// RUN: cd %t && touch ./f_33_1.swift ./f_33_2.swift ./f_33_3.swift ./f_33_4.swift ./f_33_5.swift ./f_33_6.swift ./f_33_7.swift ./f_33_8.swift ./f_33_9.swift ./f_33_10.swift
+// RUN: cd %t && touch ./f_34_1.swift ./f_34_2.swift ./f_34_3.swift ./f_34_4.swift ./f_34_5.swift ./f_34_6.swift ./f_34_7.swift ./f_34_8.swift ./f_34_9.swift ./f_34_10.swift
+// RUN: cd %t && touch ./f_35_1.swift ./f_35_2.swift ./f_35_3.swift ./f_35_4.swift ./f_35_5.swift ./f_35_6.swift ./f_35_7.swift ./f_35_8.swift ./f_35_9.swift ./f_35_10.swift
+// RUN: cd %t && touch ./f_36_1.swift ./f_36_2.swift ./f_36_3.swift ./f_36_4.swift ./f_36_5.swift ./f_36_6.swift ./f_36_7.swift ./f_36_8.swift ./f_36_9.swift ./f_36_10.swift
+// RUN: cd %t && touch ./f_37_1.swift ./f_37_2.swift ./f_37_3.swift ./f_37_4.swift ./f_37_5.swift ./f_37_6.swift ./f_37_7.swift ./f_37_8.swift ./f_37_9.swift ./f_37_10.swift
+// RUN: cd %t && touch ./f_38_1.swift ./f_38_2.swift ./f_38_3.swift ./f_38_4.swift ./f_38_5.swift ./f_38_6.swift ./f_38_7.swift ./f_38_8.swift ./f_38_9.swift ./f_38_10.swift
+// RUN: cd %t && touch ./f_39_1.swift ./f_39_2.swift ./f_39_3.swift ./f_39_4.swift ./f_39_5.swift ./f_39_6.swift ./f_39_7.swift ./f_39_8.swift ./f_39_9.swift ./f_39_10.swift
+// RUN: cd %t && touch ./f_40_1.swift ./f_40_2.swift ./f_40_3.swift ./f_40_4.swift ./f_40_5.swift ./f_40_6.swift ./f_40_7.swift ./f_40_8.swift ./f_40_9.swift ./f_40_10.swift
+// RUN: cd %t && touch ./f_41_1.swift ./f_41_2.swift ./f_41_3.swift ./f_41_4.swift ./f_41_5.swift ./f_41_6.swift ./f_41_7.swift ./f_41_8.swift ./f_41_9.swift ./f_41_10.swift
+// RUN: cd %t && touch ./f_42_1.swift ./f_42_2.swift ./f_42_3.swift ./f_42_4.swift ./f_42_5.swift ./f_42_6.swift ./f_42_7.swift ./f_42_8.swift ./f_42_9.swift ./f_42_10.swift
+// RUN: cd %t && touch ./f_43_1.swift ./f_43_2.swift ./f_43_3.swift ./f_43_4.swift ./f_43_5.swift ./f_43_6.swift ./f_43_7.swift ./f_43_8.swift ./f_43_9.swift ./f_43_10.swift
+// RUN: cd %t && touch ./f_44_1.swift ./f_44_2.swift ./f_44_3.swift ./f_44_4.swift ./f_44_5.swift ./f_44_6.swift ./f_44_7.swift ./f_44_8.swift ./f_44_9.swift ./f_44_10.swift
+// RUN: cd %t && touch ./f_45_1.swift ./f_45_2.swift ./f_45_3.swift ./f_45_4.swift ./f_45_5.swift ./f_45_6.swift ./f_45_7.swift ./f_45_8.swift ./f_45_9.swift ./f_45_10.swift
+// RUN: cd %t && touch ./f_46_1.swift ./f_46_2.swift ./f_46_3.swift ./f_46_4.swift ./f_46_5.swift ./f_46_6.swift ./f_46_7.swift ./f_46_8.swift ./f_46_9.swift ./f_46_10.swift
+// RUN: cd %t && touch ./f_47_1.swift ./f_47_2.swift ./f_47_3.swift ./f_47_4.swift ./f_47_5.swift ./f_47_6.swift ./f_47_7.swift ./f_47_8.swift ./f_47_9.swift ./f_47_10.swift
+// RUN: cd %t && touch ./f_48_1.swift ./f_48_2.swift ./f_48_3.swift ./f_48_4.swift ./f_48_5.swift ./f_48_6.swift ./f_48_7.swift ./f_48_8.swift ./f_48_9.swift ./f_48_10.swift
+// RUN: cd %t && touch ./f_49_1.swift ./f_49_2.swift ./f_49_3.swift ./f_49_4.swift ./f_49_5.swift ./f_49_6.swift ./f_49_7.swift ./f_49_8.swift ./f_49_9.swift ./f_49_10.swift
+// RUN: cd %t && touch ./f_50_1.swift ./f_50_2.swift ./f_50_3.swift ./f_50_4.swift ./f_50_5.swift ./f_50_6.swift ./f_50_7.swift ./f_50_8.swift ./f_50_9.swift ./f_50_10.swift
+// RUN: cd %t && touch ./f_51_1.swift ./f_51_2.swift ./f_51_3.swift ./f_51_4.swift ./f_51_5.swift ./f_51_6.swift ./f_51_7.swift ./f_51_8.swift ./f_51_9.swift ./f_51_10.swift
+// RUN: cd %t && touch ./f_52_1.swift ./f_52_2.swift ./f_52_3.swift ./f_52_4.swift ./f_52_5.swift ./f_52_6.swift ./f_52_7.swift ./f_52_8.swift ./f_52_9.swift ./f_52_10.swift
+// RUN: cd %t && touch ./f_53_1.swift ./f_53_2.swift ./f_53_3.swift ./f_53_4.swift ./f_53_5.swift ./f_53_6.swift ./f_53_7.swift ./f_53_8.swift ./f_53_9.swift ./f_53_10.swift
+// RUN: cd %t && touch ./f_54_1.swift ./f_54_2.swift ./f_54_3.swift ./f_54_4.swift ./f_54_5.swift ./f_54_6.swift ./f_54_7.swift ./f_54_8.swift ./f_54_9.swift ./f_54_10.swift
+// RUN: cd %t && touch ./f_55_1.swift ./f_55_2.swift ./f_55_3.swift ./f_55_4.swift ./f_55_5.swift ./f_55_6.swift ./f_55_7.swift ./f_55_8.swift ./f_55_9.swift ./f_55_10.swift
+// RUN: cd %t && touch ./f_56_1.swift ./f_56_2.swift ./f_56_3.swift ./f_56_4.swift ./f_56_5.swift ./f_56_6.swift ./f_56_7.swift ./f_56_8.swift ./f_56_9.swift ./f_56_10.swift
+// RUN: cd %t && touch ./f_57_1.swift ./f_57_2.swift ./f_57_3.swift ./f_57_4.swift ./f_57_5.swift ./f_57_6.swift ./f_57_7.swift ./f_57_8.swift ./f_57_9.swift ./f_57_10.swift
+// RUN: cd %t && touch ./f_58_1.swift ./f_58_2.swift ./f_58_3.swift ./f_58_4.swift ./f_58_5.swift ./f_58_6.swift ./f_58_7.swift ./f_58_8.swift ./f_58_9.swift ./f_58_10.swift
+// RUN: cd %t && touch ./f_59_1.swift ./f_59_2.swift ./f_59_3.swift ./f_59_4.swift ./f_59_5.swift ./f_59_6.swift ./f_59_7.swift ./f_59_8.swift ./f_59_9.swift ./f_59_10.swift
+// RUN: cd %t && touch ./f_60_1.swift ./f_60_2.swift ./f_60_3.swift ./f_60_4.swift ./f_60_5.swift ./f_60_6.swift ./f_60_7.swift ./f_60_8.swift ./f_60_9.swift ./f_60_10.swift
+// RUN: cd %t && touch ./f_61_1.swift ./f_61_2.swift ./f_61_3.swift ./f_61_4.swift ./f_61_5.swift ./f_61_6.swift ./f_61_7.swift ./f_61_8.swift ./f_61_9.swift ./f_61_10.swift
+// RUN: cd %t && touch ./f_62_1.swift ./f_62_2.swift ./f_62_3.swift ./f_62_4.swift ./f_62_5.swift ./f_62_6.swift ./f_62_7.swift ./f_62_8.swift ./f_62_9.swift ./f_62_10.swift
+// RUN: cd %t && touch ./f_63_1.swift ./f_63_2.swift ./f_63_3.swift ./f_63_4.swift ./f_63_5.swift ./f_63_6.swift ./f_63_7.swift ./f_63_8.swift ./f_63_9.swift ./f_63_10.swift
+// RUN: cd %t && touch ./f_64_1.swift ./f_64_2.swift ./f_64_3.swift ./f_64_4.swift ./f_64_5.swift ./f_64_6.swift ./f_64_7.swift ./f_64_8.swift ./f_64_9.swift ./f_64_10.swift
+// RUN: cd %t && touch ./f_65_1.swift ./f_65_2.swift ./f_65_3.swift ./f_65_4.swift ./f_65_5.swift ./f_65_6.swift ./f_65_7.swift ./f_65_8.swift ./f_65_9.swift ./f_65_10.swift
+// RUN: cd %t && touch ./f_66_1.swift ./f_66_2.swift ./f_66_3.swift ./f_66_4.swift ./f_66_5.swift ./f_66_6.swift ./f_66_7.swift ./f_66_8.swift ./f_66_9.swift ./f_66_10.swift
+// RUN: cd %t && touch ./f_67_1.swift ./f_67_2.swift ./f_67_3.swift ./f_67_4.swift ./f_67_5.swift ./f_67_6.swift ./f_67_7.swift ./f_67_8.swift ./f_67_9.swift ./f_67_10.swift
+// RUN: cd %t && touch ./f_68_1.swift ./f_68_2.swift ./f_68_3.swift ./f_68_4.swift ./f_68_5.swift ./f_68_6.swift ./f_68_7.swift ./f_68_8.swift ./f_68_9.swift ./f_68_10.swift
+// RUN: cd %t && touch ./f_69_1.swift ./f_69_2.swift ./f_69_3.swift ./f_69_4.swift ./f_69_5.swift ./f_69_6.swift ./f_69_7.swift ./f_69_8.swift ./f_69_9.swift ./f_69_10.swift
+// RUN: cd %t && touch ./f_70_1.swift ./f_70_2.swift ./f_70_3.swift ./f_70_4.swift ./f_70_5.swift ./f_70_6.swift ./f_70_7.swift ./f_70_8.swift ./f_70_9.swift ./f_70_10.swift
+// RUN: cd %t && touch ./f_71_1.swift ./f_71_2.swift ./f_71_3.swift ./f_71_4.swift ./f_71_5.swift ./f_71_6.swift ./f_71_7.swift ./f_71_8.swift ./f_71_9.swift ./f_71_10.swift
+// RUN: cd %t && touch ./f_72_1.swift ./f_72_2.swift ./f_72_3.swift ./f_72_4.swift ./f_72_5.swift ./f_72_6.swift ./f_72_7.swift ./f_72_8.swift ./f_72_9.swift ./f_72_10.swift
+// RUN: cd %t && touch ./f_73_1.swift ./f_73_2.swift ./f_73_3.swift ./f_73_4.swift ./f_73_5.swift ./f_73_6.swift ./f_73_7.swift ./f_73_8.swift ./f_73_9.swift ./f_73_10.swift
+// RUN: cd %t && touch ./f_74_1.swift ./f_74_2.swift ./f_74_3.swift ./f_74_4.swift ./f_74_5.swift ./f_74_6.swift ./f_74_7.swift ./f_74_8.swift ./f_74_9.swift ./f_74_10.swift
+// RUN: cd %t && touch ./f_75_1.swift ./f_75_2.swift ./f_75_3.swift ./f_75_4.swift ./f_75_5.swift ./f_75_6.swift ./f_75_7.swift ./f_75_8.swift ./f_75_9.swift ./f_75_10.swift
+// RUN: cd %t && touch ./f_76_1.swift ./f_76_2.swift ./f_76_3.swift ./f_76_4.swift ./f_76_5.swift ./f_76_6.swift ./f_76_7.swift ./f_76_8.swift ./f_76_9.swift ./f_76_10.swift
+// RUN: cd %t && touch ./f_77_1.swift ./f_77_2.swift ./f_77_3.swift ./f_77_4.swift ./f_77_5.swift ./f_77_6.swift ./f_77_7.swift ./f_77_8.swift ./f_77_9.swift ./f_77_10.swift
+// RUN: cd %t && touch ./f_78_1.swift ./f_78_2.swift ./f_78_3.swift ./f_78_4.swift ./f_78_5.swift ./f_78_6.swift ./f_78_7.swift ./f_78_8.swift ./f_78_9.swift ./f_78_10.swift
+// RUN: cd %t && touch ./f_79_1.swift ./f_79_2.swift ./f_79_3.swift ./f_79_4.swift ./f_79_5.swift ./f_79_6.swift ./f_79_7.swift ./f_79_8.swift ./f_79_9.swift ./f_79_10.swift
+// RUN: cd %t && touch ./f_80_1.swift ./f_80_2.swift ./f_80_3.swift ./f_80_4.swift ./f_80_5.swift ./f_80_6.swift ./f_80_7.swift ./f_80_8.swift ./f_80_9.swift ./f_80_10.swift
+// RUN: cd %t && touch ./f_81_1.swift ./f_81_2.swift ./f_81_3.swift ./f_81_4.swift ./f_81_5.swift ./f_81_6.swift ./f_81_7.swift ./f_81_8.swift ./f_81_9.swift ./f_81_10.swift
+// RUN: cd %t && touch ./f_82_1.swift ./f_82_2.swift ./f_82_3.swift ./f_82_4.swift ./f_82_5.swift ./f_82_6.swift ./f_82_7.swift ./f_82_8.swift ./f_82_9.swift ./f_82_10.swift
+// RUN: cd %t && touch ./f_83_1.swift ./f_83_2.swift ./f_83_3.swift ./f_83_4.swift ./f_83_5.swift ./f_83_6.swift ./f_83_7.swift ./f_83_8.swift ./f_83_9.swift ./f_83_10.swift
+// RUN: cd %t && touch ./f_84_1.swift ./f_84_2.swift ./f_84_3.swift ./f_84_4.swift ./f_84_5.swift ./f_84_6.swift ./f_84_7.swift ./f_84_8.swift ./f_84_9.swift ./f_84_10.swift
+// RUN: cd %t && touch ./f_85_1.swift ./f_85_2.swift ./f_85_3.swift ./f_85_4.swift ./f_85_5.swift ./f_85_6.swift ./f_85_7.swift ./f_85_8.swift ./f_85_9.swift ./f_85_10.swift
+// RUN: cd %t && touch ./f_86_1.swift ./f_86_2.swift ./f_86_3.swift ./f_86_4.swift ./f_86_5.swift ./f_86_6.swift ./f_86_7.swift ./f_86_8.swift ./f_86_9.swift ./f_86_10.swift
+// RUN: cd %t && touch ./f_87_1.swift ./f_87_2.swift ./f_87_3.swift ./f_87_4.swift ./f_87_5.swift ./f_87_6.swift ./f_87_7.swift ./f_87_8.swift ./f_87_9.swift ./f_87_10.swift
+// RUN: cd %t && touch ./f_88_1.swift ./f_88_2.swift ./f_88_3.swift ./f_88_4.swift ./f_88_5.swift ./f_88_6.swift ./f_88_7.swift ./f_88_8.swift ./f_88_9.swift ./f_88_10.swift
+// RUN: cd %t && touch ./f_89_1.swift ./f_89_2.swift ./f_89_3.swift ./f_89_4.swift ./f_89_5.swift ./f_89_6.swift ./f_89_7.swift ./f_89_8.swift ./f_89_9.swift ./f_89_10.swift
+// RUN: cd %t && touch ./f_90_1.swift ./f_90_2.swift ./f_90_3.swift ./f_90_4.swift ./f_90_5.swift ./f_90_6.swift ./f_90_7.swift ./f_90_8.swift ./f_90_9.swift ./f_90_10.swift
+// RUN: cd %t && touch ./f_91_1.swift ./f_91_2.swift ./f_91_3.swift ./f_91_4.swift ./f_91_5.swift ./f_91_6.swift ./f_91_7.swift ./f_91_8.swift ./f_91_9.swift ./f_91_10.swift
+// RUN: cd %t && touch ./f_92_1.swift ./f_92_2.swift ./f_92_3.swift ./f_92_4.swift ./f_92_5.swift ./f_92_6.swift ./f_92_7.swift ./f_92_8.swift ./f_92_9.swift ./f_92_10.swift
+// RUN: cd %t && touch ./f_93_1.swift ./f_93_2.swift ./f_93_3.swift ./f_93_4.swift ./f_93_5.swift ./f_93_6.swift ./f_93_7.swift ./f_93_8.swift ./f_93_9.swift ./f_93_10.swift
+// RUN: cd %t && touch ./f_94_1.swift ./f_94_2.swift ./f_94_3.swift ./f_94_4.swift ./f_94_5.swift ./f_94_6.swift ./f_94_7.swift ./f_94_8.swift ./f_94_9.swift ./f_94_10.swift
+// RUN: cd %t && touch ./f_95_1.swift ./f_95_2.swift ./f_95_3.swift ./f_95_4.swift ./f_95_5.swift ./f_95_6.swift ./f_95_7.swift ./f_95_8.swift ./f_95_9.swift ./f_95_10.swift
+// RUN: cd %t && touch ./f_96_1.swift ./f_96_2.swift ./f_96_3.swift ./f_96_4.swift ./f_96_5.swift ./f_96_6.swift ./f_96_7.swift ./f_96_8.swift ./f_96_9.swift ./f_96_10.swift
+// RUN: cd %t && touch ./f_97_1.swift ./f_97_2.swift ./f_97_3.swift ./f_97_4.swift ./f_97_5.swift ./f_97_6.swift ./f_97_7.swift ./f_97_8.swift ./f_97_9.swift ./f_97_10.swift
+// RUN: cd %t && touch ./f_98_1.swift ./f_98_2.swift ./f_98_3.swift ./f_98_4.swift ./f_98_5.swift ./f_98_6.swift ./f_98_7.swift ./f_98_8.swift ./f_98_9.swift ./f_98_10.swift
+// RUN: cd %t && touch ./f_99_1.swift ./f_99_2.swift ./f_99_3.swift ./f_99_4.swift ./f_99_5.swift ./f_99_6.swift ./f_99_7.swift ./f_99_8.swift ./f_99_9.swift ./f_99_10.swift
+// RUN: cd %t && touch ./f_100_1.swift ./f_100_2.swift ./f_100_3.swift ./f_100_4.swift ./f_100_5.swift ./f_100_6.swift ./f_100_7.swift ./f_100_8.swift ./f_100_9.swift ./f_100_10.swift
+// RUN: mkdir -p ./additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/
 // Force the repartitioning:
-// RUN: %swiftc_driver -driver-show-job-lifecycle -driver-batch-size-limit 10000 -driver-force-one-batch-repartition -v -c -module-name foo -o %t/additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/foo.o -emit-module -serialize-diagnostics -emit-dependencies -j 1 -enable-batch-mode %t/f_*.swift >%t/out.txt 2>&1
+// RUN: cd %t && %swiftc_driver -driver-show-job-lifecycle -driver-batch-size-limit 10000 -driver-force-one-batch-repartition -v -c -module-name foo -o ./additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/foo.o -emit-module -serialize-diagnostics -emit-dependencies -j 1 -enable-batch-mode ./f_*.swift >./out.txt 2>&1
 // RUN: %FileCheck %s <%t/out.txt
 // CHECK-NOT: unable to execute command
 // CHECK: Forming into 1 batches
@@ -113,9 +113,9 @@
 // CHECK: Forming batch job from 500 constituents
 //
 // Try it without the force; supplementary output file maps should obviate the repartition:
-// RUN: %swiftc_driver -driver-show-job-lifecycle -driver-batch-size-limit 10000 -v -c -module-name foo -o %t/additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/foo.o -emit-module -serialize-diagnostics -emit-dependencies -j 1 -enable-batch-mode %t/f_*.swift >%t/out2.txt 2>&1
+// RUN: cd %t && %swiftc_driver -driver-show-job-lifecycle -driver-batch-size-limit 10000 -v -c -module-name foo -o ./additional/path/elements/often/make/filenames/longer/than/one/might/expect/especially/given/output/directories/deep/within/a/derived/data/folder/of/a/CI/machine/foo.o -emit-module -serialize-diagnostics -emit-dependencies -j 1 -enable-batch-mode ./f_*.swift >./out2.txt 2>&1
 // RUN: %FileCheck %s <%t/out2.txt -check-prefix=NO-REPARTITION
-// CHECK-NOT: unable to execute command
+// NO-REPARTITION-NOT: unable to execute command
 // NO-REPARTITION: Forming into 1 batches
 // NO-REPARTITION: Forming batch job from 1000 constituents
 // NO-REPARTITION-NOT: Forming into 2 batches