Merge pull request #11074 from CodaFi/the-sharing-economy

Staging for __shared and __owned
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 857cda9..6c09448 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -5048,21 +5048,6 @@
     return getParameterLists()[i];
   }
 
-  /// \brief If this is a method in a type or extension thereof, compute
-  /// and return the type to be used for the 'self' argument of the interface
-  /// type, or an empty Type() if no 'self' argument should exist.  This can
-  /// only be used after name binding has resolved types.
-  ///
-  /// \param isInitializingCtor Specifies whether we're computing the 'self'
-  /// type of an initializing constructor, which accepts an instance 'self'
-  /// rather than a metatype 'self'.
-  ///
-  /// \param wantDynamicSelf Specifies whether the 'self' type should be
-  /// wrapped in a DynamicSelfType, which is the case for the 'self' parameter
-  /// type inside a class method returning 'Self'.
-  Type computeInterfaceSelfType(bool isInitializingCtor=false,
-                                bool wantDynamicSelf=false);
-
   /// \brief This method returns the implicit 'self' decl.
   ///
   /// Note that some functions don't have an implicit 'self' decl, for example,
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 97e67d3..ee079a7 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -4819,6 +4819,22 @@
   bool inOut = paramTy->is<InOutType>();
   return {isVariadic, autoclosure, escaping, inOut, isShared};
 }
+  
+/// \brief If this is a method in a type or extension thereof, compute
+/// and return a parameter to be used for the 'self' argument.  The type of
+/// the parameter is the empty Type() if no 'self' argument should exist. This
+/// can only be used after name binding has resolved types.
+///
+/// \param isInitializingCtor Specifies whether we're computing the 'self'
+/// type of an initializing constructor, which accepts an instance 'self'
+/// rather than a metatype 'self'.
+///
+/// \param wantDynamicSelf Specifies whether the 'self' type should be
+/// wrapped in a DynamicSelfType, which is the case for the 'self' parameter
+/// type inside a class method returning 'Self'.
+AnyFunctionType::Param computeSelfParam(AbstractFunctionDecl *AFD,
+                                        bool isInitializingCtor=false,
+                                        bool wantDynamicSelf=false);
 
 #define TYPE(id, parent)
 #define SUGARED_TYPE(id, parent) \
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 8305984..3f2815b 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -1210,11 +1210,11 @@
          ARGS(ErrorPtrTy, Int8PtrPtrTy, OpenedErrorTriplePtrTy),
          ATTRS(NoUnwind))
 
-// void __tsan_write1(void *addr);
+// void __tsan_external_write(void *addr, void *caller_pc, void *tag);
 // This is a Thread Sanitizer instrumentation entry point in compiler-rt.
-FUNCTION(TSanInoutAccess, __tsan_write1, C_CC,
+FUNCTION(TSanInoutAccess, __tsan_external_write, C_CC,
          RETURNS(VoidTy),
-         ARGS(Int8PtrTy),
+         ARGS(Int8PtrTy, Int8PtrTy, Int8PtrTy),
          ATTRS(NoUnwind))
 
 FUNCTION(GetKeyPath, swift_getKeyPath, C_CC,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 3a1b36a..04bf012 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2775,6 +2775,61 @@
   return Ty;
 }
 
+AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
+                                               bool isInitializingCtor,
+                                               bool wantDynamicSelf) {
+  auto *dc = AFD->getDeclContext();
+  auto &Ctx = dc->getASTContext();
+  
+  // Determine the type of the container.
+  auto containerTy = dc->getDeclaredInterfaceType();
+  if (!containerTy || containerTy->hasError())
+    return AnyFunctionType::Param(ErrorType::get(Ctx), Identifier(),
+                                  ParameterTypeFlags());
+
+  // Determine the type of 'self' inside the container.
+  auto selfTy = dc->getSelfInterfaceType();
+  if (!selfTy || selfTy->hasError())
+    return AnyFunctionType::Param(ErrorType::get(Ctx), Identifier(),
+                                  ParameterTypeFlags());
+
+  bool isStatic = false;
+  bool isMutating = false;
+
+  if (auto *FD = dyn_cast<FuncDecl>(AFD)) {
+    isStatic = FD->isStatic();
+    isMutating = FD->isMutating();
+
+    if (wantDynamicSelf && FD->hasDynamicSelf())
+      selfTy = DynamicSelfType::get(selfTy, Ctx);
+  } else if (isa<ConstructorDecl>(AFD)) {
+    if (isInitializingCtor) {
+      // initializing constructors of value types always have an implicitly
+      // inout self.
+      isMutating = true;
+    } else {
+      // allocating constructors have metatype 'self'.
+      isStatic = true;
+    }
+  } else if (isa<DestructorDecl>(AFD)) {
+    // destructors of value types always have an implicitly inout self.
+    isMutating = true;
+  }
+
+  // 'static' functions have 'self' of type metatype<T>.
+  if (isStatic)
+    return AnyFunctionType::Param(MetatypeType::get(selfTy, Ctx), Identifier(),
+                                  ParameterTypeFlags());
+
+  // Reference types have 'self' of type T.
+  if (containerTy->hasReferenceSemantics())
+    return AnyFunctionType::Param(selfTy, Identifier(),
+                                  ParameterTypeFlags());
+
+  return AnyFunctionType::Param(selfTy, Identifier(),
+                                ParameterTypeFlags().withInOut(isMutating));
+}
+
 void UnboundGenericType::Profile(llvm::FoldingSetNodeID &ID,
                                  GenericTypeDecl *TheDecl, Type Parent) {
   ID.AddPointer(TheDecl);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e435e39..7de5535 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2403,14 +2403,19 @@
     underlying = mapTypeOutOfContext(underlying);
   UnderlyingTy.setType(underlying);
 
-  // Create a NameAliasType which will resolve to the underlying type.
-  ASTContext &Ctx = getASTContext();
-  auto aliasTy = new (Ctx, AllocationArena::Permanent) NameAliasType(this);
-  aliasTy->setRecursiveProperties(getUnderlyingTypeLoc().getType()
-      ->getRecursiveProperties());
+  // FIXME -- if we already have an interface type, we're changing the
+  // underlying type. See the comment in the ProtocolDecl case of
+  // validateDecl().
+  if (!hasInterfaceType()) {
+    // Create a NameAliasType which will resolve to the underlying type.
+    ASTContext &Ctx = getASTContext();
+    auto aliasTy = new (Ctx, AllocationArena::Permanent) NameAliasType(this);
+    aliasTy->setRecursiveProperties(getUnderlyingTypeLoc().getType()
+        ->getRecursiveProperties());
 
-  // Set the interface type of this declaration.
-  setInterfaceType(MetatypeType::get(aliasTy, Ctx));
+    // Set the interface type of this declaration.
+    setInterfaceType(MetatypeType::get(aliasTy, Ctx));
+  }
 }
 
 UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
@@ -4412,61 +4417,6 @@
   return { getSubscriptLoc(), ElementTy.getSourceRange().End };
 }
 
-Type AbstractFunctionDecl::computeInterfaceSelfType(bool isInitializingCtor,
-                                                    bool wantDynamicSelf) {
-  auto *dc = getDeclContext();
-  auto &Ctx = dc->getASTContext();
-  
-  // Determine the type of the container.
-  auto containerTy = dc->getDeclaredInterfaceType();
-  if (!containerTy || containerTy->hasError())
-    return ErrorType::get(Ctx);
-
-  // Determine the type of 'self' inside the container.
-  auto selfTy = dc->getSelfInterfaceType();
-  if (!selfTy || selfTy->hasError())
-    return ErrorType::get(Ctx);
-
-  bool isStatic = false;
-  bool isMutating = false;
-
-  if (auto *FD = dyn_cast<FuncDecl>(this)) {
-    isStatic = FD->isStatic();
-    isMutating = FD->isMutating();
-
-    if (wantDynamicSelf && FD->hasDynamicSelf())
-      selfTy = DynamicSelfType::get(selfTy, Ctx);
-  } else if (isa<ConstructorDecl>(this)) {
-    if (isInitializingCtor) {
-      // initializing constructors of value types always have an implicitly
-      // inout self.
-      isMutating = true;
-    } else {
-      // allocating constructors have metatype 'self'.
-      isStatic = true;
-    }
-  } else if (isa<DestructorDecl>(this)) {
-    // destructors of value types always have an implicitly inout self.
-    isMutating = true;
-  }
-
-  // 'static' functions have 'self' of type metatype<T>.
-  if (isStatic)
-    return MetatypeType::get(selfTy, Ctx);
-
-  // Reference types have 'self' of type T.
-  if (containerTy->hasReferenceSemantics())
-    return selfTy;
-
-  // Mutating methods are always passed inout so we can receive the side
-  // effect.
-  if (isMutating)
-    return InOutType::get(selfTy);
-
-  // Nonmutating methods on structs and enums pass the receiver by value.
-  return selfTy;
-}
-
 DeclName AbstractFunctionDecl::getEffectiveFullName() const {
   if (getFullName())
     return getFullName();
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index e9a95db..1d726bf 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -250,7 +250,18 @@
   llvm::Function *fn = cast<llvm::Function>(IGM.getTSanInoutAccessFn());
 
   llvm::Value *castAddress = Builder.CreateBitCast(address, IGM.Int8PtrTy);
-  Builder.CreateCall(fn, {castAddress});
+
+  // Passing 0 as the caller PC causes compiler-rt to get our PC.
+  llvm::Value *callerPC = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
+
+  // A magic number agreed upon with compiler-rt to indicate a modifying
+  // access.
+  const unsigned kExternalTagSwiftModifyingAccess = 0x1;
+  llvm::Value *tagValue =
+      llvm::ConstantInt::get(IGM.SizeTy, kExternalTagSwiftModifyingAccess);
+  llvm::Value *castTag = Builder.CreateIntToPtr(tagValue, IGM.Int8PtrTy);
+
+  Builder.CreateCall(fn, {castAddress, callerPC, castTag});
 }
 
 
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 9973f28..845b7bd 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -511,48 +511,76 @@
     void visitTopLevelParams(AbstractionPattern origType,
                              CanAnyFunctionType::CanParamArrayRef params,
                              AnyFunctionType::ExtInfo extInfo) {
-      // If we don't have 'self', we don't need to do anything special.
-      if (!extInfo.hasSelfParam() && !Foreign.Self.isImportAsMember()) {
-        // Add any leading foreign parameters.
-        maybeAddForeignParameters();
-
-        if (params.empty()) {
-          visit(origType, M.getASTContext().TheEmptyTupleType);
-        } else {
-          CanType ty = AnyFunctionType::composeInput(M.getASTContext(), params,
-                                                     /*canonicalVararg*/true)
-                        ->getCanonicalType();
-          visit(origType, ty);
-        }
-        return;
-      }
-
-      // Okay, handle 'self'.
-
       unsigned numEltTypes = params.size();
-      assert(numEltTypes > 0);
       unsigned numNonSelfParams = numEltTypes - 1;
-
+      
       // We have to declare this out here so that the lambda scope lasts for
       // the duration of the loop below.
       auto handleForeignSelf = [&] {
         visit(origType.getTupleElementType(numNonSelfParams),
               params[numNonSelfParams].getType());
       };
-
+      
       // If we have a foreign-self, install handleSelf as the handler.
       if (Foreign.Self.isInstance()) {
+        assert(numEltTypes > 0);
         // This is safe because function_ref just stores a pointer to the
         // existing lambda object.
         HandleForeignSelf = handleForeignSelf;
       }
-
-      // Now we can add any leading foreign parameters.
+      
+      // Add any leading foreign parameters.
       maybeAddForeignParameters();
+      
+      // If we have no parameters, even 'self' parameters, bail unless we need
+      // to substitute.
+      if (params.empty()) {
+        if (origType.isTypeParameter())
+          visit(origType, M.getASTContext().TheEmptyTupleType);
+        return;
+      }
+      
+      assert(numEltTypes > 0);
+      
+      // If we don't have 'self', we don't need to do anything special.
+      if (!extInfo.hasSelfParam() && !Foreign.Self.isImportAsMember()) {
+        CanType ty = AnyFunctionType::composeInput(M.getASTContext(), params,
+                                                   /*canonicalVararg*/true)
+                        ->getCanonicalType();
+        CanTupleType tty = dyn_cast<TupleType>(ty);
+        if (!tty || (origType.isTypeParameter() && !tty->hasInOutElement())) {
+          visit(origType, ty);
+          return;
+        }
+        
+        // If the abstraction pattern is opaque, and the tuple type is
+        // materializable -- if it doesn't contain an l-value type -- then it's
+        // a valid target for substitution and we should not expand it.
+        for (auto i : indices(tty.getElementTypes())) {
+          visit(origType.getTupleElementType(i), tty.getElementType(i));
+        }
+        return;
+      }
+      
+      // Okay, handle 'self'.
 
       // Process all the non-self parameters.
       for (unsigned i = 0; i != numNonSelfParams; ++i) {
-        visit(origType.getTupleElementType(i), params[i].getType());
+        CanType ty =  params[i].getType();
+        CanTupleType tty = dyn_cast<TupleType>(ty);
+        AbstractionPattern eltPattern = origType.getTupleElementType(i);
+        if (!tty || (eltPattern.isTypeParameter() && !tty->hasInOutElement())) {
+          visit(eltPattern, ty);
+          continue;
+        }
+        
+        assert(eltPattern.isTuple());
+        // If the abstraction pattern is opaque, and the tuple type is
+        // materializable -- if it doesn't contain an l-value type -- then it's
+        // a valid target for substitution and we should not expand it.
+        for (unsigned j = 0; j < eltPattern.getNumTupleElements(); ++j) {
+          visit(eltPattern.getTupleElementType(j), tty.getElementType(j));
+        }
       }
 
       // Process the self parameter.  Note that we implicitly drop self
@@ -568,15 +596,10 @@
     }
 
     void visit(AbstractionPattern origType, CanType substType) {
-      // Expand tuples.  But if the abstraction pattern is opaque, and
-      // the tuple type is materializable -- if it doesn't contain an
-      // l-value type -- then it's a valid target for substitution and
-      // we should not expand it.
+      // Expand tuples.
       CanTupleType substTupleTy = dyn_cast<TupleType>(substType);
-      if (substTupleTy &&
-          (!origType.isTypeParameter() || substTupleTy->hasInOutElement())) {
-        assert(origType.isTypeParameter() ||
-               origType.getNumTupleElements() == substTupleTy->getNumElements());
+      if (substTupleTy && !origType.isTypeParameter()) {
+        assert(origType.getNumTupleElements() == substTupleTy->getNumElements());
         for (auto i : indices(substTupleTy.getElementTypes())) {
           visit(origType.getTupleElementType(i),
                 substTupleTy.getElementType(i));
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index ab627d2..727353d 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -1092,8 +1092,8 @@
       ArgumentSource self = [&] {
         if (!baseLV.isValid()) {
           return ArgumentSource();
-        } else if (cast<FuncDecl>(setter.getDecl())->computeInterfaceSelfType()
-                     ->is<InOutType>()) {
+        } else if (computeSelfParam(cast<FuncDecl>(setter.getDecl()))
+                     .getParameterFlags().isInOut()) {
           return ArgumentSource(loc, std::move(baseLV));
         } else {
           return emitBaseValueForAccessor(SGF, loc, std::move(baseLV),
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index aa1ae8b..0f9f82e 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -435,7 +435,7 @@
     }
 
     CanType witnessSelfType =
-      Witness->computeInterfaceSelfType()->getCanonicalType(
+      computeSelfParam(Witness).getType()->getCanonicalType(
         GenericSig, *SGM.M.getSwiftModule());
     witnessSelfType = getSubstWitnessInterfaceType(witnessSelfType);
 
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index a74dee1..a194283 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -1068,21 +1068,23 @@
     initDecl->getAttrs().add(reqAttr);
   }
 
-  Type selfType = initDecl->computeInterfaceSelfType();
-  Type selfInitType = initDecl->computeInterfaceSelfType(/*init=*/true);
+  auto selfParam = computeSelfParam(initDecl);
+  auto initSelfParam = computeSelfParam(initDecl, /*init=*/true);
   Type interfaceType;
   Type initializerType;
   if (auto sig = target->getGenericSignatureOfContext()) {
     // Evaluate the below, but in a generic environment (if Self is generic).
     initDecl->setGenericEnvironment(target->getGenericEnvironmentOfContext());
-    interfaceType = GenericFunctionType::get(sig, selfType, innerType,
+    interfaceType = GenericFunctionType::get(sig, {selfParam}, innerType,
                                              FunctionType::ExtInfo());
-    initializerType = GenericFunctionType::get(sig, selfInitType, innerType,
+    initializerType = GenericFunctionType::get(sig, {initSelfParam}, innerType,
                                                FunctionType::ExtInfo());
   } else {
     // (Self) -> (Decoder) throws -> (Self)
-    interfaceType = FunctionType::get(selfType, innerType);
-    initializerType = FunctionType::get(selfInitType, innerType);
+    interfaceType = FunctionType::get({selfParam}, innerType,
+                                      FunctionType::ExtInfo());
+    initializerType = FunctionType::get({initSelfParam}, innerType,
+                                        FunctionType::ExtInfo());
   }
 
   initDecl->setInterfaceType(interfaceType);
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index bac6fc5..a271c5f 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -159,26 +159,25 @@
   Type retInterfaceType =
       OptionalType::get(parentDC->getDeclaredInterfaceType());
   Type interfaceType = FunctionType::get(interfaceArgType, retInterfaceType);
-  Type selfInterfaceType = initDecl->computeInterfaceSelfType();
-  Type selfInitializerInterfaceType =
-      initDecl->computeInterfaceSelfType(/*init*/ true);
+  auto selfParam = computeSelfParam(initDecl);
+  auto initSelfParam = computeSelfParam(initDecl, /*init*/ true);
 
   Type allocIfaceType;
   Type initIfaceType;
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     initDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
 
-    allocIfaceType = GenericFunctionType::get(sig, selfInterfaceType,
+    allocIfaceType = GenericFunctionType::get(sig, {selfParam},
                                               interfaceType,
                                               FunctionType::ExtInfo());
-    initIfaceType = GenericFunctionType::get(sig, selfInitializerInterfaceType,
+    initIfaceType = GenericFunctionType::get(sig, {initSelfParam},
                                              interfaceType,
                                              FunctionType::ExtInfo());
   } else {
-    allocIfaceType = FunctionType::get(selfInterfaceType,
-                                       interfaceType);
-    initIfaceType = FunctionType::get(selfInitializerInterfaceType,
-                                      interfaceType);
+    allocIfaceType = FunctionType::get({selfParam},
+                                       interfaceType, FunctionType::ExtInfo());
+    initIfaceType = FunctionType::get({initSelfParam},
+                                      interfaceType, FunctionType::ExtInfo());
   }
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 245ae54..cc6e63e 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -277,7 +277,7 @@
 
   // Compute the interface type.
   Type interfaceTy;
-  Type selfIfaceTy = eqDecl->computeInterfaceSelfType();
+  auto selfParam = computeSelfParam(eqDecl);
   if (auto genericSig = parentDC->getGenericSignatureOfContext()) {
     eqDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
 
@@ -288,11 +288,12 @@
     auto ifaceParamsTy = TupleType::get(ifaceParamElts, C);
     interfaceTy = FunctionType::get(ifaceParamsTy, boolTy,
                                     AnyFunctionType::ExtInfo());
-    interfaceTy = GenericFunctionType::get(genericSig, selfIfaceTy, interfaceTy,
+    interfaceTy = GenericFunctionType::get(genericSig, {selfParam}, interfaceTy,
                                            AnyFunctionType::ExtInfo());
   } else {
     interfaceTy = FunctionType::get(paramsTy, boolTy);
-    interfaceTy = FunctionType::get(selfIfaceTy, interfaceTy);
+    interfaceTy = FunctionType::get({selfParam}, interfaceTy,
+                                    FunctionType::ExtInfo());
   }
   eqDecl->setInterfaceType(interfaceTy);
 
@@ -419,13 +420,14 @@
 
   // Compute the interface type of hashValue().
   Type interfaceType;
-  Type selfIfaceType = getterDecl->computeInterfaceSelfType();
+  auto selfParam = computeSelfParam(getterDecl);
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     getterDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
-    interfaceType = GenericFunctionType::get(sig, selfIfaceType, methodType,
+    interfaceType = GenericFunctionType::get(sig, {selfParam}, methodType,
                                              AnyFunctionType::ExtInfo());
   } else
-    interfaceType = FunctionType::get(selfIfaceType, methodType);
+    interfaceType = FunctionType::get({selfParam}, methodType,
+                                      AnyFunctionType::ExtInfo());
   
   getterDecl->setInterfaceType(interfaceType);
   getterDecl->setAccessibility(std::max(Accessibility::Internal,
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 6b01759..b509bfe 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -296,26 +296,25 @@
   Type retInterfaceType
     = OptionalType::get(parentDC->getDeclaredInterfaceType());
   Type interfaceType = FunctionType::get(interfaceArgType, retInterfaceType);
-  Type selfInterfaceType = initDecl->computeInterfaceSelfType();
-  Type selfInitializerInterfaceType
-    = initDecl->computeInterfaceSelfType(/*init*/ true);
+  auto selfParam = computeSelfParam(initDecl);
+  auto initSelfParam = computeSelfParam(initDecl, /*init*/ true);
 
   Type allocIfaceType;
   Type initIfaceType;
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     initDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
 
-    allocIfaceType = GenericFunctionType::get(sig, selfInterfaceType,
+    allocIfaceType = GenericFunctionType::get(sig, {selfParam},
                                               interfaceType,
                                               FunctionType::ExtInfo());
-    initIfaceType = GenericFunctionType::get(sig, selfInitializerInterfaceType,
+    initIfaceType = GenericFunctionType::get(sig, {initSelfParam},
                                              interfaceType,
                                              FunctionType::ExtInfo());
   } else {
-    allocIfaceType = FunctionType::get(selfInterfaceType,
-                                       interfaceType);
-    initIfaceType = FunctionType::get(selfInitializerInterfaceType,
-                                      interfaceType);
+    allocIfaceType = FunctionType::get({selfParam},
+                                       interfaceType, FunctionType::ExtInfo());
+    initIfaceType = FunctionType::get({initSelfParam},
+                                      interfaceType, FunctionType::ExtInfo());
   }
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 5c890bb..6e31c4d 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -160,15 +160,16 @@
   // Compute the interface type of the getter.
   Type interfaceType = FunctionType::get(TupleType::getEmpty(C),
                                          propertyInterfaceType);
-  Type selfInterfaceType = getterDecl->computeInterfaceSelfType();
+  auto selfParam = computeSelfParam(getterDecl);
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     getterDecl->setGenericEnvironment(
         parentDC->getGenericEnvironmentOfContext());
-    interfaceType = GenericFunctionType::get(sig, selfInterfaceType,
+    interfaceType = GenericFunctionType::get(sig, {selfParam},
                                              interfaceType,
                                              FunctionType::ExtInfo());
   } else
-    interfaceType = FunctionType::get(selfInterfaceType, interfaceType);
+    interfaceType = FunctionType::get({selfParam}, interfaceType,
+                                      FunctionType::ExtInfo());
   getterDecl->setInterfaceType(interfaceType);
   getterDecl->setAccessibility(std::max(typeDecl->getFormalAccess(),
                                         Accessibility::Internal));
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 6ed2b76..8397811 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1268,31 +1268,29 @@
   auto selfDecl = func->getImplicitSelfDecl();
 
   // Compute the type of self.
-  Type selfIfaceTy = func->computeInterfaceSelfType(/*isInitializingCtor*/true,
-                                                    /*wantDynamicSelf*/true);
-  assert(selfDecl && selfIfaceTy && "Not a method");
+  auto selfParam = computeSelfParam(func, /*isInitializingCtor*/true,
+                                    /*wantDynamicSelf*/true);
+  assert(selfDecl && selfParam.getPlainType() && "Not a method");
 
   // 'self' is 'let' for reference types (i.e., classes) or when 'self' is
   // neither inout.
-  auto specifier = selfIfaceTy->is<InOutType>()
+  auto specifier = selfParam.getParameterFlags().isInOut()
                  ? VarDecl::Specifier::InOut
                  : VarDecl::Specifier::Owned;
   selfDecl->setSpecifier(specifier);
 
-  selfDecl->setInterfaceType(selfIfaceTy->getInOutObjectType());
+  selfDecl->setInterfaceType(selfParam.getPlainType());
 }
 
 /// Record the context type of 'self' after the generic environment of
 /// the function has been determined.
 static void recordSelfContextType(AbstractFunctionDecl *func) {
   auto selfDecl = func->getImplicitSelfDecl();
-  Type selfTy = func->computeInterfaceSelfType(/*isInitializingCtor*/true,
-                                               /*wantDynamicSelf*/true);
+  auto selfParam = computeSelfParam(func, /*isInitializingCtor*/true,
+                                    /*wantDynamicSelf*/true);
 
-  selfTy = func->mapTypeIntoContext(selfTy);
-  // FIXME(Remove InOutType): 'computeInterfaceSelfType' should tell us if
-  // we need to do this.
-  if (selfTy->is<InOutType>()) {
+  auto selfTy = func->mapTypeIntoContext(selfParam.getType());
+  if (selfParam.getParameterFlags().isInOut()) {
     selfDecl->setSpecifier(VarDecl::Specifier::InOut);
   }
   selfDecl->setType(selfTy->getInOutObjectType());
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index bb0b691..2ea8901 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -858,22 +858,12 @@
     SmallVector<AnyFunctionType::Param, 4> argTy;
     SmallVector<AnyFunctionType::Param, 4> initArgTy;
     
-    if (i == e-1 && hasSelf) {
-      auto ifTy = func->computeInterfaceSelfType();
-      auto selfTy = AnyFunctionType::Param(ifTy->getInOutObjectType(),
-                                           Identifier(),
-                                           ParameterTypeFlags().withInOut(ifTy->is<InOutType>()));
-      
+    if (i == e-1 && hasSelf) {      
       // Substitute in our own 'self' parameter.
       
-      argTy.push_back(selfTy);
+      argTy.push_back(computeSelfParam(func));
       if (initFuncTy) {
-        auto ifTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/true);
-
-        initArgTy.push_back(
-          AnyFunctionType::Param(
-            ifTy->getInOutObjectType(),
-            Identifier(), ParameterTypeFlags().withInOut(ifTy->is<InOutType>())));
+        initArgTy.push_back(computeSelfParam(func, /*isInitializingCtor=*/true));
       }
     } else {
       AnyFunctionType::decomposeInput(paramLists[e - i - 1]->getInterfaceType(Context), argTy);
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 0ebc461..b80eb73 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -3032,6 +3032,14 @@
   }
 
   if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(member)) {
+    // FIXME: If this is a protocol typealias and we haven't built the
+    // protocol's generic environment yet, do so now, to ensure the
+    // typealias's underlying type has fully resoved dependent
+    // member types.
+    if (auto *protoDecl = dyn_cast<ProtocolDecl>(aliasDecl->getDeclContext()))
+      if (protoDecl->getGenericEnvironment() == nullptr)
+        validateDecl(protoDecl);
+
     if (aliasDecl->getGenericParams()) {
       return UnboundGenericType::get(
           aliasDecl, baseTy,
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 5283ac7..053b832 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2651,15 +2651,15 @@
 
     // Set the initializer interface type of the constructor.
     auto allocType = ctor->getInterfaceType();
-    auto selfTy = ctor->computeInterfaceSelfType(/*isInitializingCtor=*/true);
+    auto selfParam = computeSelfParam(ctor, /*isInitializingCtor=*/true);
     if (auto polyFn = allocType->getAs<GenericFunctionType>()) {
       ctor->setInitializerInterfaceType(
               GenericFunctionType::get(polyFn->getGenericSignature(),
-                                       selfTy, polyFn->getResult(),
+                                       {selfParam}, polyFn->getResult(),
                                        polyFn->getExtInfo()));
     } else {
       auto fn = allocType->castTo<FunctionType>();
-      ctor->setInitializerInterfaceType(FunctionType::get(selfTy,
+      ctor->setInitializerInterfaceType(FunctionType::get({selfParam},
                                                           fn->getResult(),
                                                           fn->getExtInfo()));
     }
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index b92ee16..d75e576 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -766,8 +766,10 @@
       switch s._variantBuffer {
         case .native(let buffer):
           _variantBuffer = .native(buffer)
+#if _runtime(_ObjC)
         case .cocoa(let owner):
           _variantBuffer = .cocoa(owner)
+#endif
       }
     } else {
       for item in sequence {
@@ -1238,17 +1240,13 @@
       }
       return true
 
+  #if _runtime(_ObjC)
     case (_VariantSetBuffer.cocoa(let lhsCocoa),
         _VariantSetBuffer.cocoa(let rhsCocoa)):
-  #if _runtime(_ObjC)
       return _stdlib_NSObject_isEqual(lhsCocoa.cocoaSet, rhsCocoa.cocoaSet)
-  #else
-        _sanityCheckFailure("internal error: unexpected cocoa set")
-  #endif
 
     case (_VariantSetBuffer.native(let lhsNative),
       _VariantSetBuffer.cocoa(let rhsCocoa)):
-  #if _runtime(_ObjC)
 
       if lhsNative.count != rhsCocoa.count {
         return false
@@ -1270,15 +1268,9 @@
         return false
       }
       return true
-  #else
-        _sanityCheckFailure("internal error: unexpected cocoa set")
-  #endif
 
     case (_VariantSetBuffer.cocoa, _VariantSetBuffer.native):
-  #if _runtime(_ObjC)
       return rhs == lhs
-  #else
-        _sanityCheckFailure("internal error: unexpected cocoa set")
   #endif
     }
   }
@@ -2622,16 +2614,12 @@
       }
       return true
 
-    case (.cocoa(let lhsCocoa), .cocoa(let rhsCocoa)):
   #if _runtime(_ObjC)
+    case (.cocoa(let lhsCocoa), .cocoa(let rhsCocoa)):
       return _stdlib_NSObject_isEqual(
         lhsCocoa.cocoaDictionary, rhsCocoa.cocoaDictionary)
-  #else
-      _sanityCheckFailure("internal error: unexpected cocoa dictionary")
-  #endif
 
     case (.native(let lhsNative), .cocoa(let rhsCocoa)):
-  #if _runtime(_ObjC)
 
       if lhsNative.count != rhsCocoa.count {
         return false
@@ -2654,15 +2642,9 @@
         continue
       }
       return true
-  #else
-      _sanityCheckFailure("internal error: unexpected cocoa dictionary")
-  #endif
 
     case (.cocoa, .native):
-  #if _runtime(_ObjC)
       return rhs == lhs
-  #else
-      _sanityCheckFailure("internal error: unexpected cocoa dictionary")
   #endif
     }
   }
@@ -4436,10 +4418,6 @@
     _sanityCheckFailure("this function should never be called")
   }
 }
-#else
-@_versioned
-@_fixed_layout
-internal struct _Cocoa${Self}Buffer {}
 #endif
 
 @_versioned
@@ -4448,7 +4426,9 @@
 
   internal typealias NativeBuffer = _Native${Self}Buffer<${TypeParameters}>
   internal typealias NativeIndex = _Native${Self}Index<${TypeParameters}>
+#if _runtime(_ObjC)
   internal typealias CocoaBuffer = _Cocoa${Self}Buffer
+#endif
   internal typealias SequenceElement = ${Sequence}
   internal typealias SequenceElementWithoutLabels = ${Sequence}
   internal typealias SelfType = _Variant${Self}Buffer
@@ -4459,7 +4439,9 @@
 %end
 
   case native(NativeBuffer)
+#if _runtime(_ObjC)
   case cocoa(CocoaBuffer)
+#endif
 
   @_versioned
   @_transparent
@@ -4477,10 +4459,12 @@
     switch self {
     case .native:
       return _isUnique_native(&self)
+#if _runtime(_ObjC)
     case .cocoa:
       // Don't consider Cocoa buffer mutable, even if it is mutable and is
       // uniquely referenced.
       return false
+#endif
     }
   }
 
@@ -4490,8 +4474,10 @@
       switch self {
       case .native(let buffer):
         return buffer
+#if _runtime(_ObjC)
       case .cocoa:
         _sanityCheckFailure("internal error: not backed by native buffer")
+#endif
       }
     }
     set {
@@ -4552,8 +4538,8 @@
       return (reallocated: true,
               capacityChanged: oldCapacity != newNativeBuffer.capacity)
 
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       let cocoa${Self} = cocoaBuffer.cocoa${Self}
       var newNativeBuffer = NativeBuffer(minimumCapacity: minimumCapacity)
       let oldCocoaIterator = _Cocoa${Self}Iterator(cocoa${Self})
@@ -4576,8 +4562,6 @@
 
       self = .native(newNativeBuffer)
       return (reallocated: true, capacityChanged: true)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4616,11 +4600,9 @@
     case .native:
       return Int(Double(asNative.capacity) /
         _hashContainerDefaultMaxLoadFactorInverse)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return cocoaBuffer.count
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4639,11 +4621,9 @@
     switch self {
     case .native:
       return ._native(asNative.startIndex)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return ._cocoa(cocoaBuffer.startIndex)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4656,11 +4636,9 @@
     switch self {
     case .native:
       return ._native(asNative.endIndex)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return ._cocoa(cocoaBuffer.endIndex)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4674,11 +4652,9 @@
     switch self {
     case .native:
       return ._native(asNative.index(after: i._nativeIndex))
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return ._cocoa(cocoaBuffer.index(after: i._cocoaIndex))
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4704,15 +4680,13 @@
         return ._native(nativeIndex)
       }
       return nil
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
       if let cocoaIndex = cocoaBuffer.index(forKey: anyObjectKey) {
         return ._cocoa(cocoaIndex)
       }
       return nil
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4725,8 +4699,8 @@
     switch self {
     case .native:
       return asNative.assertingGet(i._nativeIndex)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
 %if Self == 'Set':
       let anyObjectValue: AnyObject = cocoaBuffer.assertingGet(i._cocoaIndex)
       let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
@@ -4738,8 +4712,6 @@
       let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
       return (nativeKey, nativeValue)
 %end
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4752,14 +4724,12 @@
     switch self {
     case .native:
       return asNative.assertingGet(key)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       // FIXME: This assumes that Key and Value are bridged verbatim.
       let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
       let anyObjectValue: AnyObject = cocoaBuffer.assertingGet(anyObjectKey)
       return _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4788,11 +4758,9 @@
     switch self {
     case .native:
       return asNative.maybeGet(key)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return SelfType.maybeGetFromCocoaBuffer(cocoaBuffer, forKey: key)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4846,12 +4814,10 @@
     switch self {
     case .native:
       return nativeUpdateValue(value, forKey: key)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       migrateDataToNativeBuffer(cocoaBuffer)
       return nativeUpdateValue(value, forKey: key)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4872,8 +4838,8 @@
     switch self {
     case .native:
       return nativePointerToValue(at: i)
-    case .cocoa(let cocoaStorage):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaStorage):
       // We have to migrate the data to native storage before we can return a
       // mutable pointer. But after we migrate, the Cocoa index becomes
       // useless, so get the key first.
@@ -4885,8 +4851,6 @@
       let nativeIndex = asNative.index(forKey: key)!
 
       return nativePointerToValue(at: ._native(nativeIndex))
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4938,12 +4902,10 @@
     switch self {
     case .native:
       return nativeInsert(value, forKey: key)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       migrateDataToNativeBuffer(cocoaBuffer)
       return nativeInsert(value, forKey: key)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -4978,8 +4940,8 @@
     switch self {
     case .native:
       return try nativeMapValues(transform)
-    case .cocoa(let cocoaStorage):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaStorage):
       var storage: _Variant${Self}Buffer<Key, T> = .native(
         _Native${Self}Buffer<Key, T>(capacity: cocoaStorage.count))
 
@@ -4993,8 +4955,6 @@
       }
 
       return storage
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5042,12 +5002,10 @@
     switch self {
     case .native:
       try nativeMerge(keysAndValues, uniquingKeysWith: combine)
-    case .cocoa(let cocoaStorage):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaStorage):
       migrateDataToNativeBuffer(cocoaStorage)
       try nativeMerge(keysAndValues, uniquingKeysWith: combine)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5203,8 +5161,8 @@
     switch self {
     case .native:
       return nativeRemove(at: index._nativeIndex)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       // We have to migrate the data first.  But after we do so, the Cocoa
       // index becomes useless, so get the key first.
       //
@@ -5222,8 +5180,6 @@
 %elif Self == 'Dictionary':
       return (key, value._unsafelyUnwrappedUnchecked)
 %end
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5237,16 +5193,14 @@
     switch self {
     case .native:
       return nativeRemoveObject(forKey: key)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
       if cocoaBuffer.maybeGet(anyObjectKey) == nil {
         return nil
       }
       migrateDataToNativeBuffer(cocoaBuffer)
       return nativeRemoveObject(forKey: key)
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5287,11 +5241,9 @@
     switch self {
     case .native:
       nativeRemoveAll()
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       self = .native(NativeBuffer(minimumCapacity: cocoaBuffer.count))
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5304,11 +5256,9 @@
     switch self {
     case .native:
       return asNative.count
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return cocoaBuffer.count
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5323,11 +5273,9 @@
     case .native(let buffer):
       return ._native(
         start: asNative.startIndex, end: asNative.endIndex, buffer: buffer)
-    case .cocoa(let cocoaBuffer):
 #if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
       return ._cocoa(_Cocoa${Self}Iterator(cocoaBuffer.cocoa${Self}))
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
@@ -5441,17 +5389,19 @@
 % end
 
 }
-#else
-internal struct _Cocoa${Self}Index {}
 #endif
 
 internal enum ${Self}IndexRepresentation<${TypeParametersDecl}> {
   typealias _Index = ${Self}Index<${TypeParameters}>
   typealias _NativeIndex = _Index._NativeIndex
+#if _runtime(_ObjC)
   typealias _CocoaIndex = _Index._CocoaIndex
+#endif
 
   case _native(_NativeIndex)
+#if _runtime(_ObjC)
   case _cocoa(_CocoaIndex)
+#endif
 }
 
 extension ${Self} {
@@ -5484,7 +5434,9 @@
   // type for bridged NS${Self} in terms of Cocoa enumeration facilities.
 
   internal typealias _NativeIndex = _Native${Self}Index<${TypeParameters}>
+#if _runtime(_ObjC)
   internal typealias _CocoaIndex = _Cocoa${Self}Index
+#endif
 
 %if Self == 'Set':
   internal typealias Key = ${TypeParameters}
@@ -5515,8 +5467,10 @@
     switch _value {
     case ._native(let nativeIndex):
       return nativeIndex
+#if _runtime(_ObjC)
     case ._cocoa:
       _sanityCheckFailure("internal error: does not contain a native index")
+#endif
     }
   }
 
@@ -5550,11 +5504,9 @@
     switch (lhs._value, rhs._value) {
     case (._native(let lhsNative), ._native(let rhsNative)):
       return lhsNative == rhsNative
-    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
   #if _runtime(_ObjC)
+    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
       return lhsCocoa == rhsCocoa
-  #else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
   #endif
     default:
       _preconditionFailure("comparing indexes from different sets")
@@ -5572,11 +5524,9 @@
     switch (lhs._value, rhs._value) {
     case (._native(let lhsNative), ._native(let rhsNative)):
       return lhsNative < rhsNative
-    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
   #if _runtime(_ObjC)
+    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
       return lhsCocoa < rhsCocoa
-  #else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
   #endif
     default:
       _preconditionFailure("comparing indexes from different sets")
@@ -5665,8 +5615,6 @@
 %end
   }
 }
-#else
-final internal class _Cocoa${Self}Iterator {}
 #endif
 
 @_versioned
@@ -5684,7 +5632,9 @@
   // state, so it should keep its own reference to the buffer.
   case _native(
     start: _NativeIndex, end: _NativeIndex, buffer: _NativeBuffer)
+#if _runtime(_ObjC)
   case _cocoa(_Cocoa${Self}Iterator)
+#endif
 }
 
 /// An iterator over the members of a `${Self}<${TypeParameters}>`.
@@ -5743,8 +5693,10 @@
       _state =
         ._native(start: buffer.index(after: startIndex), end: endIndex, buffer: buffer)
       return result
+#if _runtime(_ObjC)
     case ._cocoa:
       _sanityCheckFailure("internal error: not backed by NS${Self}")
+#endif
     }
   }
 
@@ -5761,8 +5713,8 @@
     switch _state {
     case ._native:
       return _nativeNext()
-    case ._cocoa(let cocoaIterator):
 #if _runtime(_ObjC)
+    case ._cocoa(let cocoaIterator):
 %if Self == 'Set':
       if let anyObjectElement = cocoaIterator.next() {
         return _forceBridgeFromObjectiveC(anyObjectElement, Element.self)
@@ -5775,8 +5727,6 @@
       }
 %end
       return nil
-#else
-      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
 #endif
     }
   }
diff --git a/test/IRGen/tsan_instrumentation.sil b/test/IRGen/tsan_instrumentation.sil
index 690033a..48c952f 100644
--- a/test/IRGen/tsan_instrumentation.sil
+++ b/test/IRGen/tsan_instrumentation.sil
@@ -23,7 +23,7 @@
 bb0:
   %0 = global_addr @_T020tsan_instrumentation1gSiv : $*Int
   %1 = builtin "tsanInoutAccess"(%0 : $*Int) : $()
-// CHECK:  call void @__tsan_write1(i8* bitcast ([[GLOBAL]]* @_T020tsan_instrumentation1gSiv to i8*))
+// CHECK:  call void @__tsan_external_write(i8* bitcast ([[GLOBAL]]* @_T020tsan_instrumentation1gSiv to i8*), i8* null, i8* inttoptr ({{(i32|i64)}} 1 to i8*))
 
   %2 = tuple ()
   return %2 : $()
diff --git a/test/Sanitizers/tsan-inout.swift b/test/Sanitizers/tsan-inout.swift
index b592677..6919706 100644
--- a/test/Sanitizers/tsan-inout.swift
+++ b/test/Sanitizers/tsan-inout.swift
@@ -76,7 +76,7 @@
         thread: { _ = globalForGlobalStructMutatingMethod.read() },
         thread: { globalForGlobalStructMutatingMethod.mutate() } )
 // CHECK-LABEL: Running GlobalStructMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is global
 
 var globalForGlobalStructDifferentStoredPropertiesInout = UninstrumentedStruct()
@@ -84,7 +84,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalStructDifferentStoredPropertiesInout.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalStructDifferentStoredPropertiesInout.storedProperty2) } )
 // CHECK-LABEL: Running GlobalStructDifferentStoredPropertiesInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is global
 
 var globalForGlobalStructSameStoredPropertyInout = UninstrumentedStruct()
@@ -92,7 +92,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalStructSameStoredPropertyInout.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalStructSameStoredPropertyInout.storedProperty1) } )
 // CHECK-LABEL: Running GlobalStructSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 
 
 var globalForGlobalStructSubscriptDifferentIndexesInout = UninstrumentedStruct()
@@ -100,7 +100,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalStructSubscriptDifferentIndexesInout[0]) },
         thread: { uninstrumentedTakesInout(&globalForGlobalStructSubscriptDifferentIndexesInout[1]) } )
 // CHECK-LABEL: Running GlobalStructSubscriptDifferentIndexes
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is global
 
 
@@ -109,7 +109,7 @@
         thread: { _ = globalForGlobalStructSubscriptDifferentIndexesGetSet[0] },
         thread: { globalForGlobalStructSubscriptDifferentIndexesGetSet[1] = 12 } )
 // CHECK-LABEL: Running GlobalStructSubscriptDifferentIndexesGetSet
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is global
 
 var globalForGlobalClassGeneralMethods = UninstrumentedClass()
@@ -117,21 +117,21 @@
         thread: { _ = globalForGlobalClassGeneralMethods.read() },
         thread: { globalForGlobalClassGeneralMethods.mutate() } )
 // CHECK-LABEL: Running GlobalClassGeneralMethods
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 var globalForGlobalClassDifferentStoredPropertiesInout = UninstrumentedClass()
 testRace(name: "GlobalClassDifferentStoredPropertiesInout",
         thread: { uninstrumentedTakesInout(&globalForGlobalClassDifferentStoredPropertiesInout.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalClassDifferentStoredPropertiesInout.storedProperty2) } )
 // CHECK-LABEL: Running GlobalClassDifferentStoredPropertiesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 var globalForGlobalClassSubscriptDifferentIndexesInout = UninstrumentedClass()
 testRace(name: "GlobalClassSubscriptDifferentIndexesInout",
         thread: { uninstrumentedTakesInout(&globalForGlobalClassSubscriptDifferentIndexesInout[0]) },
         thread: { uninstrumentedTakesInout(&globalForGlobalClassSubscriptDifferentIndexesInout[1]) } )
 // CHECK-LABEL: Running GlobalClassSubscriptDifferentIndexesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 
 var globalForGlobalClassSameStoredPropertyInout = UninstrumentedClass()
@@ -139,7 +139,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalClassSameStoredPropertyInout.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalClassSameStoredPropertyInout.storedProperty1) } )
 // CHECK-LABEL: Running GlobalClassSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 
 // These access a global declared in the TSanUninstrumented module
@@ -147,7 +147,7 @@
         thread: { uninstrumentedTakesInout(&storedGlobalInUninstrumentedModule1) },
         thread: { uninstrumentedTakesInout(&storedGlobalInUninstrumentedModule1) } )
 // CHECK-LABEL: Running InoutAccessToStoredGlobalInUninstrumentedModule
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is global
 
 // These access a global declared in the TSanUninstrumented module.
@@ -165,14 +165,14 @@
         thread: { uninstrumentedTakesInout(&computedGlobalInUninstrumentedModule1) },
         thread: { uninstrumentedTakesInout(&computedGlobalInUninstrumentedModule1) } )
 // CHECK-LABEL: Running InoutAccessToComputedGlobalInUninstrumentedModule
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 // These access a computed global declared in the TSanUninstrumented module
 testRace(name: "ReadAndWriteToComputedGlobalInUninstrumentedModule",
         thread: { computedGlobalInUninstrumentedModule2 = 7 },
         thread: { _ = computedGlobalInUninstrumentedModule2 } )
 // CHECK-LABEL: Running ReadAndWriteToComputedGlobalInUninstrumentedModule
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 
 
@@ -183,7 +183,7 @@
         thread: { _ = globalForGlobalUninstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.read() },
         thread: { globalForGlobalUninstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.mutate() } )
 // CHECK-LABEL: Running GlobalUninstrumentedClassStoredPropertyMutatingMethod
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 // Note: TSan doesn't see a race above because it doesn't see any load on the
 // read side because the getter for the class property is not instrumented.
@@ -194,7 +194,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassStoredPropertyInout.storedStructProperty.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassStoredPropertyInout.storedStructProperty.storedProperty2) } )
 // CHECK-LABEL: Running GlobalUninstrumentedClassStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 
 // Note: TSan sees the race above because the inout instrumentation adds an
@@ -206,7 +206,7 @@
         thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassComputedPropertyInout.computedStructProperty.storedProperty1) },
         thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassComputedPropertyInout.computedStructProperty.storedProperty1) } )
 // CHECK-LABEL: Running GlobalUninstrumentedClassComputedPropertyInout
-// CHECK-NO: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 // In the above the write in instrumented code is to the value buffer allocated
 // at the call site so there is no data race if the getter and setters themselves
@@ -219,7 +219,7 @@
         thread: { _ = globalForGlobalInstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.read() },
         thread: { globalForGlobalInstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.mutate() } )
 // CHECK-LABEL: Running GlobalInstrumentedClassStoredPropertyMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 //
 // TSan does see this above race because the getter and materializeForSet is instrumented
@@ -250,7 +250,7 @@
          thread: { l.mutate() } )
 }
 // CHECK-LABEL: Running CapturedLocalStructMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 
 
@@ -261,7 +261,7 @@
          thread: { uninstrumentedTakesInout(&l.storedProperty2) } )
 }
 // CHECK-LABEL: Running CapturedLocalStructDifferentStoredPropertiesInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 
 
@@ -272,7 +272,7 @@
           thread: { l.mutate() } )
 }
 // CHECK-LABEL: Running CapturedLocalClassGeneralMethods
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 
 func runCapturedLocalDifferentStoredPropertiesInout() {
@@ -282,7 +282,7 @@
           thread: { uninstrumentedTakesInout(&l.storedProperty2) } )
 }
 // CHECK-LABEL: Running CapturedLocalClassDifferentStoredPropertiesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
 
 func runCapturedLocalSameStoredPropertyInout() {
   let l = UninstrumentedClass()
@@ -291,7 +291,7 @@
           thread: { uninstrumentedTakesInout(&l.storedProperty1) } )
 }
 // CHECK-LABEL: Running CapturedLocalClassSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
 // CHECK: Location is heap block
 
 runLocalTests()
diff --git a/validation-test/compiler_crashers/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift b/validation-test/compiler_crashers/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
new file mode 100644
index 0000000..aac84e2
--- /dev/null
+++ b/validation-test/compiler_crashers/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol A{{}protocol A{func a:Self.a}typealias e:A.a
diff --git a/validation-test/compiler_crashers/28822-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift b/validation-test/compiler_crashers/28822-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift
new file mode 100644
index 0000000..89bf788
--- /dev/null
+++ b/validation-test/compiler_crashers/28822-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+extension CountableRange{{}func a<a:A
+protocol A{typealias e:a{}class a
diff --git a/validation-test/compiler_crashers/28823-impl-getgraphindex-typevariables-size-out-of-bounds-index.swift b/validation-test/compiler_crashers/28823-impl-getgraphindex-typevariables-size-out-of-bounds-index.swift
new file mode 100644
index 0000000..c8ddcec
--- /dev/null
+++ b/validation-test/compiler_crashers/28823-impl-getgraphindex-typevariables-size-out-of-bounds-index.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+{{}as ManagedBuffer}{
diff --git a/validation-test/compiler_crashers/28824-hasval.swift b/validation-test/compiler_crashers/28824-hasval.swift
new file mode 100644
index 0000000..ac9769e
--- /dev/null
+++ b/validation-test/compiler_crashers/28824-hasval.swift
@@ -0,0 +1,12 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+extension CountableRange{protocol b{typealias a:RangeReplaceableCollection
+protocol P{}
+class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift b/validation-test/compiler_crashers/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
new file mode 100644
index 0000000..58385b5
--- /dev/null
+++ b/validation-test/compiler_crashers/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol b:a{init(t:a}class a{class a
diff --git a/validation-test/compiler_crashers/28826-type-haserror-should-not-be-assigning-a-type-involving-errortype.swift b/validation-test/compiler_crashers/28826-type-haserror-should-not-be-assigning-a-type-involving-errortype.swift
new file mode 100644
index 0000000..83f9939
--- /dev/null
+++ b/validation-test/compiler_crashers/28826-type-haserror-should-not-be-assigning-a-type-involving-errortype.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol A{{}protocol a{extension{class a<a{let d=a(class a<P
diff --git a/validation-test/compiler_crashers_2_fixed/0114-rdar33189068.swift b/validation-test/compiler_crashers_2_fixed/0114-rdar33189068.swift
new file mode 100644
index 0000000..aaa271d
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0114-rdar33189068.swift
@@ -0,0 +1,19 @@
+// RUN: %target-swift-frontend %s -typecheck
+
+struct Bar : BarProtocol {
+    typealias Element = Int
+}
+
+struct Foo: FooProtocol {
+    typealias Things = Bar
+    func thing() -> Thing {}
+}
+
+protocol BarProtocol {
+    associatedtype Element
+}
+
+protocol FooProtocol {
+    associatedtype Things: BarProtocol
+    typealias Thing = Things.Element
+}
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index 35b5cf9..6c6b106 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -129,8 +129,10 @@
   switch s._variantBuffer {
   case .native:
     return true
+#if _runtime(_ObjC)
   case .cocoa:
     return false
+#endif
   }
 }