Merge pull request #4538 from apple/stdlib-warning-suppression

[stdlib] Suppress noisy warnings
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index a549804..bbae689 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,68 +1,13 @@
-<!-- Please complete this template before creating the pull request. -->
-#### What's in this pull request?
-<!-- Description about pull request. -->
+<!-- What's in this pull request? -->
+Replace this paragraph with a description of your changes and rationale. Provide links to external references/discussions if appropriate.
 
-#### Resolved bug number: ([SR-](https://bugs.swift.org/browse/SR-))
-<!-- If this pull request resolves any bugs from Swift bug tracker -->
+<!-- If this pull request resolves any bugs in the Swift bug tracker, provide a link: -->
+Resolves [SR-NNNN](https://bugs.swift.org/browse/SR-NNNN).
 
-* * * *
+<!--
+Before merging this pull request, you must run the Swift continuous integration tests.
+For information about triggering CI builds via @swift-ci, see:
+https://github.com/apple/swift/blob/master/docs/ContinuousIntegration.md#swift-ci
 
-<!-- This selection should only be completed by Swift admin -->
-Before merging this pull request to apple/swift repository:
-- [ ] Test pull request on Swift continuous integration.
-
-<details>
-  <summary>Triggering Swift CI</summary>
-
-The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:
-
-**Smoke Testing**
-
-        Platform     | Comment
-        ------------ | -------------
-        All supported platforms     | @swift-ci Please smoke test
-        All supported platforms     | @swift-ci Please smoke test and merge
-        OS X platform               | @swift-ci Please smoke test OS X platform
-        Linux platform              | @swift-ci Please smoke test Linux platform
-
-A smoke test on macOS does the following:
-
-1. Builds the compiler incrementally.
-2. Builds the standard library only for macOS. Simulator standard libraries and
-   device standard libraries are not built.
-3. lldb is not built.
-4. The test and validation-test targets are run only for macOS. The optimized
-   version of these tests are not run.
-
-A smoke test on Linux does the following:
-
-1. Builds the compiler incrementally.
-2. Builds the standard library incrementally.
-3. lldb is built incrementally.
-4. The swift test and validation-test targets are run. The optimized version of these
-   tests are not run.
-5. lldb is tested.
-
-**Validation Testing**
-
-        Platform     | Comment
-        ------------ | -------------
-        All supported platforms     | @swift-ci Please test
-        All supported platforms     | @swift-ci Please clean test
-        All supported platforms     | @swift-ci Please test and merge
-        OS X platform               | @swift-ci Please test OS X platform
-        OS X platform               | @swift-ci Please clean test OS X platform
-        OS X platform               | @swift-ci Please benchmark
-        Linux platform              | @swift-ci Please test Linux platform
-        Linux platform              | @swift-ci Please clean test Linux platform
-
-
-**Lint Testing**
-
-        Language     | Comment
-        ------------ | -------------
-        Python       | @swift-ci Please Python lint
-
-Note: Only members of the Apple organization can trigger swift-ci.
-</details>
-<!-- Thank you for your contribution to Swift! -->
+Thank you for your contribution to Swift!
+-->
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e883e04..9af53bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -126,10 +126,6 @@
 set(SWIFT_ENABLE_GOLD_LINKER FALSE CACHE BOOL
     "Enable using the gold linker when available")
 
-# Configure and initialize swift components.
-include(SwiftComponents)
-swift_configure_components()
-
 set(SWIFT_SDKS "" CACHE STRING
     "If non-empty, limits building target binaries only to specified SDKs (despite other SDKs being available)")
 
@@ -331,6 +327,7 @@
 
 include(CheckCXXSourceRuns)
 include(CMakeParseArguments)
+include(SwiftComponents)
 include(SwiftHandleGybSources)
 include(SwiftSetIfArchBitness)
 include(SwiftSource)
@@ -339,7 +336,8 @@
 include(SwiftComponents)
 include(SwiftList)
 
-swift_configure_install_components("${SWIFT_INSTALL_COMPONENTS}")
+# Configure swift include, install, build components.
+swift_configure_components()
 
 if("${CMAKE_VERSION}" VERSION_LESS "3.0")
   set(SWIFT_CMAKE_HAS_GENERATOR_EXPRESSIONS FALSE)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e36bf96..0283424 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,6 +5,7 @@
 
 ---
 
-Before submitting the pull request, please make sure you have tested your
-changes and that they follow the Swift project [guidelines for contributing
+Before submitting the pull request, please make sure you have [tested your
+changes](https://github.com/apple/swift/blob/master/docs/ContinuousIntegration.md)
+and that they follow the Swift project [guidelines for contributing
 code](https://swift.org/contributing/#contributing-code).
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 3d3033f..51ea877 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -1881,3 +1881,22 @@
 macro(add_swift_lib_subdirectory name)
   add_llvm_subdirectory(SWIFT LIB ${name})
 endmacro()
+
+function(add_swift_host_tool executable)
+  cmake_parse_arguments(
+      ADDSWIFTHOSTTOOL # prefix
+      "" # options
+      "" # single-value args
+      "SWIFT_COMPONENT" # multi-value args
+      ${ARGN})
+
+  # Create the executable rule.
+  add_swift_executable(${executable} ${ADDSWIFTHOSTTOOL_UNPARSED_ARGUMENTS})
+
+  # And then create the install rule if we are asked to.
+  if (ADDSWIFTHOSTTOOL_SWIFT_COMPONENT)
+    swift_install_in_component(${ADDSWIFTHOSTTOOL_SWIFT_COMPONENT}
+      TARGETS ${executable}
+      RUNTIME DESTINATION bin)
+  endif()
+endfunction()
diff --git a/cmake/modules/SwiftComponents.cmake b/cmake/modules/SwiftComponents.cmake
index 92734d5..3d58409 100644
--- a/cmake/modules/SwiftComponents.cmake
+++ b/cmake/modules/SwiftComponents.cmake
@@ -71,6 +71,23 @@
   # Set the SWIFT_INSTALL_COMPONENTS variable to the default value if it is not passed in via -D
   set(SWIFT_INSTALL_COMPONENTS "${_SWIFT_DEFINED_COMPONENTS}" CACHE STRING
     "A semicolon-separated list of components to install ${_SWIFT_DEFINED_COMPONENTS}")
+
+  foreach(component ${_SWIFT_DEFINED_COMPONENTS})
+    string(TOUPPER "${component}" var_name_piece)
+    string(REPLACE "-" "_" var_name_piece "${var_name_piece}")
+    set(SWIFT_INSTALL_${var_name_piece} FALSE)
+  endforeach()
+
+  foreach(component ${SWIFT_INSTALL_COMPONENTS})
+    list(FIND _SWIFT_DEFINED_COMPONENTS "${component}" index)
+    if(${index} EQUAL -1)
+      message(FATAL_ERROR "unknown install component: ${component}")
+    endif()
+
+    string(TOUPPER "${component}" var_name_piece)
+    string(REPLACE "-" "_" var_name_piece "${var_name_piece}")
+    set(SWIFT_INSTALL_${var_name_piece} TRUE)
+  endforeach()
 endmacro()
 
 function(swift_is_installing_component component result_var_name)
@@ -105,22 +122,3 @@
     install(${ARGN})
   endif()
 endfunction()
-
-macro(swift_configure_install_components install_components)
-  foreach(component ${_SWIFT_DEFINED_COMPONENTS})
-    string(TOUPPER "${component}" var_name_piece)
-    string(REPLACE "-" "_" var_name_piece "${var_name_piece}")
-    set(SWIFT_INSTALL_${var_name_piece} FALSE)
-  endforeach()
-
-  foreach(component ${install_components})
-    list(FIND _SWIFT_DEFINED_COMPONENTS "${component}" index)
-    if(${index} EQUAL -1)
-      message(FATAL_ERROR "unknown install component: ${component}")
-    endif()
-
-    string(TOUPPER "${component}" var_name_piece)
-    string(REPLACE "-" "_" var_name_piece "${var_name_piece}")
-    set(SWIFT_INSTALL_${var_name_piece} TRUE)
-  endforeach()
-endmacro()
diff --git a/cmake/modules/SwiftUtils.cmake b/cmake/modules/SwiftUtils.cmake
index 3484f7c..05b4cc9 100644
--- a/cmake/modules/SwiftUtils.cmake
+++ b/cmake/modules/SwiftUtils.cmake
@@ -106,3 +106,20 @@
     message(FATAL_ERROR "Unknown build type: ${build_type}")
   endif()
 endfunction()
+
+# Set variable to value if value is not null or false. Otherwise set variable to
+# default_value.
+function(set_with_default variable value)
+  cmake_parse_argument(
+    SWD
+    ""
+    "DEFAULT"
+    "" ${ARGN})
+  precondition(SWD_DEFAULT
+    MESSAGE "Must specify a default argument")
+  if (value)
+    set(${variable} ${value} PARENT_SCOPE)
+  else()
+    set(${variable} ${SWD_DEFAULT} PARENT_SCOPE)
+  endif()
+endfunction()
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index 8a2a713..ec91751 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -33,12 +33,12 @@
 
 ### Smoke Testing
 
-        Platform     | Comment
-        ------------ | -------------
-        All supported platforms     | @swift-ci Please smoke test
-        All supported platforms     | @swift-ci Please smoke test and merge
-        OS X platform               | @swift-ci Please smoke test OS X platform
-        Linux platform              | @swift-ci Please smoke test Linux platform
+        Platform     | Comment | Check Status
+        ------------ | ------- | ------------
+        All supported platforms     | @swift-ci Please smoke test       		 | Swift Test Linux Platform (smoke test) <br> Swift Test OS X Platform (smoke test)
+        All supported platforms     | @swift-ci Please smoke test and merge		 | Swift Test Linux Platform (smoke test) <br> Swift Test OS X Platform (smoke test)
+        OS X platform               | @swift-ci Please smoke test OS X platform  | Swift Test OS X Platform (smoke test)
+        Linux platform              | @swift-ci Please smoke test Linux platform | Swift Test Linux Platform (smoke test)
 
 A smoke test on macOS does the following:
 
@@ -64,12 +64,16 @@
 
 ### Validation Testing
 
-        Platform     | Comment
-        ------------ | -------------
-        All supported platforms     | @swift-ci Please test
-        All supported platforms     | @swift-ci Please test and merge
-        OS X platform               | @swift-ci Please test OS X platform
-        Linux platform              | @swift-ci Please test Linux platform
+        Platform     | Comment | Check Status
+        ------------ | ------- | ------------
+        All supported platforms     | @swift-ci Please test							| Swift Test Linux Platform (smoke test)<br>Swift Test OS X Platform (smoke test)<br>Swift Test Linux Platform<br>Swift Test OS X Platform<br>  
+        All supported platforms     | @swift-ci Please clean test					| Swift Test Linux Platform (smoke test)<br>Swift Test OS X Platform (smoke test)<br>Swift Test Linux Platform<br>Swift Test OS X Platform<br>  
+        All supported platforms     | @swift-ci Please test and merge				| Swift Test Linux Platform (smoke test) <br> Swift Test OS X Platform (smoke test)<br> Swift Test Linux Platform <br>Swift Test OS X Platform
+        OS X platform               | @swift-ci Please test OS X platform 			| Swift Test OS X Platform (smoke test)<br>Swift Test OS X Platform
+        OS X platform               | @swift-ci Please clean test OS X platform     | Swift Test OS X Platform (smoke test)<br>Swift Test OS X Platform
+        OS X platform               | @swift-ci Please benchmark                    | Swift Benchmark on OS X Platform
+        Linux platform              | @swift-ci Please test Linux platform          | Swift Test Linux Platform (smoke test) <br> Swift Test Linux Platform
+        Linux platform              | @swift-ci Please clean test Linux platform    | Swift Test Linux Platform (smoke test) <br> Swift Test Linux Platform
 
 The core principles of validation testing is that:
 
@@ -102,15 +106,15 @@
 
 ### Benchmarking
 
-        Platform       | Comment
-        ------------   | -------------
-        OS X platform  | @swift-ci Please benchmark
+        Platform     | Comment | Check Status
+        ------------ | ------- | ------------
+        OS X platform  | @swift-ci Please benchmark | Swift Benchmark on OS X Platform
 
 ### Lint Testing
 
-        Language     | Comment
-        ------------ | -------------
-        Python       | @swift-ci Please Python lint
+        Language     | Comment | Check Status
+        ------------ | ------- | ------------
+        Python       | @swift-ci Please Python lint | Python lint
 
 ## Cross Repository Testing
 
@@ -134,6 +138,7 @@
 
 6. Watch the public incremental build on ci.swift.org to make sure that you did not make any mistakes. It should complete within 30-40 minutes depending on what else was being committed in the mean time.
 
+
 ## ci.swift.org bots
 
 FIXME: FILL ME IN!
diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h
index 78e8c15..9c7a5b0 100644
--- a/include/swift/AST/ArchetypeBuilder.h
+++ b/include/swift/AST/ArchetypeBuilder.h
@@ -250,11 +250,19 @@
   /// \brief Get a generic signature based on the provided complete list
   /// of generic parameter types.
   ///
-  /// \returns a generic signature build based on the provided list of
+  /// \returns a generic signature built from the provided list of
   ///          generic parameter types.
   GenericSignature *
   getGenericSignature(ArrayRef<GenericTypeParamType *> genericParamsTypes);
 
+  /// \brief Get a generic context based on the complete list of generic
+  /// parameter types.
+  ///
+  /// \returns a generic context built from the provided list of
+  ///          generic parameter types.
+  GenericEnvironment *getGenericEnvironment(
+      ArrayRef<GenericTypeParamType *> genericParamsTypes);
+
   /// Infer requirements from the given type, recursively.
   ///
   /// This routine infers requirements from a type that occurs within the
@@ -315,27 +323,20 @@
   /// parameter.
   ArchetypeType *getArchetype(GenericTypeParamDecl *GenericParam);
 
-  /// \brief Retrieve the array of all of the archetypes produced during
-  /// archetype assignment. The 'primary' archetypes will occur first in this
-  /// list.
-  ArrayRef<ArchetypeType *> getAllArchetypes();
-  
   /// Map an interface type to a contextual type.
-  static Type mapTypeIntoContext(const DeclContext *dc, Type type,
-                                 LazyResolver *resolver = nullptr);
+  static Type mapTypeIntoContext(const DeclContext *dc, Type type);
 
   /// Map an interface type to a contextual type.
   static Type mapTypeIntoContext(ModuleDecl *M,
-                                 GenericParamList *genericParams,
-                                 Type type,
-                                 LazyResolver *resolver = nullptr);
+                                 GenericEnvironment *genericEnv,
+                                 Type type);
 
   /// Map a contextual type to an interface type.
   static Type mapTypeOutOfContext(const DeclContext *dc, Type type);
 
   /// Map a contextual type to an interface type.
   static Type mapTypeOutOfContext(ModuleDecl *M,
-                                  GenericParamList *genericParams,
+                                  GenericEnvironment *genericEnv,
                                   Type type);
 
   using SameTypeRequirement
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 964a2dc..e1512f0 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -35,6 +35,7 @@
   enum class AccessSemantics : unsigned char;
   class ApplyExpr;
   class ArchetypeBuilder;
+  class GenericEnvironment;
   class ArchetypeType;
   class ASTContext;
   class ASTPrinter;
@@ -1059,7 +1060,6 @@
   unsigned NumParams;
   SourceLoc WhereLoc;
   MutableArrayRef<RequirementRepr> Requirements;
-  ArrayRef<ArchetypeType *> AllArchetypes;
 
   GenericParamList *OuterParameters;
 
@@ -1109,28 +1109,6 @@
                                   MutableArrayRef<RequirementRepr> Requirements,
                                   SourceLoc RAngleLoc);
 
-  /// Create a new generic parameter list with the same parameters and
-  /// requirements as this one, but parented to a different outer parameter
-  /// list.
-  GenericParamList *cloneWithOuterParameters(const ASTContext &Context,
-                                             GenericParamList *Outer) {
-    auto clone = create(Context,
-                        SourceLoc(),
-                        getParams(),
-                        SourceLoc(),
-                        getRequirements(),
-                        SourceLoc());
-    clone->setAllArchetypes(getAllArchetypes());
-    clone->setOuterParameters(Outer);
-    return clone;
-  }
-  
-  /// Create an empty generic parameter list.
-  static GenericParamList *getEmpty(ASTContext &Context) {
-    // TODO: Could probably unique this in the AST context.
-    return create(Context, SourceLoc(), {}, SourceLoc(), {}, SourceLoc());
-  }
-  
   MutableArrayRef<GenericTypeParamDecl *> getParams() {
     return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
   }
@@ -1148,12 +1126,6 @@
   const_iterator begin() const { return getParams().begin(); }
   const_iterator end() const { return getParams().end(); }
 
-  /// Get the total number of parameters, including those from parent generic
-  /// parameter lists.
-  unsigned totalSize() const {
-    return NumParams + (OuterParameters ? OuterParameters->totalSize() : 0);
-  }
-  
   /// \brief Retrieve the location of the 'where' keyword, or an invalid
   /// location if 'where' was not present.
   SourceLoc getWhereLoc() const { return WhereLoc; }
@@ -1199,24 +1171,7 @@
   /// main part of a declaration's signature.
   void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc,
                               ArrayRef<RequirementRepr> trailingRequirements);
-
-  /// \brief Retrieves the list containing all archetypes described by this
-  /// generic parameter clause.
-  ///
-  /// In this list of archetypes, the primary archetypes come first followed by
-  /// any non-primary archetypes (i.e., those archetypes that encode associated
-  /// types of another archetype).
-  ///
-  /// This does not include archetypes from the outer generic parameter list(s).
-  ArrayRef<ArchetypeType *> getAllArchetypes() const { return AllArchetypes; }
   
-  /// \brief Sets all archetypes *without* copying the source array.
-  void setAllArchetypes(ArrayRef<ArchetypeType *> AA) {
-    assert(AA.size() >= size()
-           && "allArchetypes is smaller than number of generic params?!");
-    AllArchetypes = AA;
-  }
-
   /// \brief Retrieve the outer generic parameter list, which provides the
   /// generic parameters of the context in which this generic parameter list
   /// exists.
@@ -1270,36 +1225,6 @@
     return depth;
   }
 
-  /// Derive a contextual type substitution map from a substitution array.
-  /// This is just like GenericSignature::getSubstitutionMap(), except
-  /// with contextual types instead of interface types.
-  void
-  getSubstitutionMap(ModuleDecl *mod,
-                     GenericSignature *sig,
-                     ArrayRef<Substitution> subs,
-                     TypeSubstitutionMap &subsMap,
-                     ArchetypeConformanceMap &conformanceMap) const;
-
-  /// Derive the all-archetypes list for the given list of generic
-  /// parameters.
-  static ArrayRef<ArchetypeType*>
-  deriveAllArchetypes(ArrayRef<GenericTypeParamDecl*> params,
-                      SmallVectorImpl<ArchetypeType*> &archetypes);
-
-  void getForwardingSubstitutionMap(TypeSubstitutionMap &result) const;
-
-  ArrayRef<Substitution>
-  getForwardingSubstitutions(GenericSignature *sig) const;
-
-  /// Collect the nested archetypes of an archetype into the given
-  /// collection.
-  ///
-  /// \param known - the set of archetypes already present in `all`
-  /// \param all - the output list of archetypes
-  static void addNestedArchetypes(ArchetypeType *archetype,
-                                  SmallPtrSetImpl<ArchetypeType*> &known,
-                                  SmallVectorImpl<ArchetypeType*> &all);
-  
   void print(raw_ostream &OS);
   void dump();
 };
@@ -1472,6 +1397,12 @@
   /// the parsed representation, and not part of the module file.
   GenericSignature *GenericSig = nullptr;
 
+  /// \brief The generic context of this extension.
+  ///
+  /// This is the mapping between interface types and archetypes for the
+  /// generic parameters of this extension.
+  GenericEnvironment *GenericEnv = nullptr;
+
   MutableArrayRef<TypeLoc> Inherited;
 
   /// The trailing where clause.
@@ -1555,7 +1486,19 @@
   GenericSignature *getGenericSignature() const { return GenericSig; }
 
   /// Set the generic signature of this extension.
-  void setGenericSignature(GenericSignature *sig);
+  void setGenericSignature(GenericSignature *sig) {
+    assert(!GenericSig && "Already have generic signature");
+    GenericSig = sig;
+  }
+
+  /// Retrieve the generic context for this extension.
+  GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
+
+  /// Set the generic context of this extension.
+  void setGenericEnvironment(GenericEnvironment *env) {
+    assert(!GenericEnv && "Already have generic context");
+    GenericEnv = env;
+  }
 
   /// Retrieve the generic requirements.
   ArrayRef<Requirement> getGenericRequirements() const;
@@ -2306,6 +2249,12 @@
   /// the parsed representation, and not part of the module file.
   GenericSignature *GenericSig = nullptr;
 
+  /// \brief The generic context of this type.
+  ///
+  /// This is the mapping between interface types and archetypes for the
+  /// generic parameters of this type.
+  GenericEnvironment *GenericEnv = nullptr;
+
   /// \brief Whether or not the generic signature of the type declaration is
   /// currently being validated.
   // TODO: Merge into GenericSig bits.
@@ -2324,7 +2273,10 @@
   void setGenericParams(GenericParamList *params);
 
   /// Set the generic signature of this type.
-  void setGenericSignature(GenericSignature *sig);
+  void setGenericSignature(GenericSignature *sig) {
+    assert(!GenericSig && "Already have generic signature");
+    GenericSig = sig;
+  }
 
   /// Retrieve the innermost generic parameter types.
   ArrayRef<GenericTypeParamType *> getInnermostGenericParamTypes() const {
@@ -2355,6 +2307,15 @@
     return ValidatingGenericSignature;
   }
 
+  /// Retrieve the generic context for this type.
+  GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
+
+  /// Set the generic context of this type.
+  void setGenericEnvironment(GenericEnvironment *env) {
+    assert(!this->GenericEnv && "already have generic context?");
+    this->GenericEnv = env;
+  }
+
   // Resolve ambiguity due to multiple base classes.
   using TypeDecl::getASTContext;
   using DeclContext::operator new;
@@ -4573,6 +4534,7 @@
 
   GenericParamList *GenericParams;
   GenericSignature *GenericSig;
+  GenericEnvironment *GenericEnv;
 
   CaptureInfo Captures;
 
@@ -4589,7 +4551,7 @@
       : ValueDecl(Kind, Parent, Name, NameLoc),
         DeclContext(DeclContextKind::AbstractFunctionDecl, Parent),
         Body(nullptr), GenericParams(nullptr), GenericSig(nullptr),
-        ThrowsLoc(ThrowsLoc) {
+        GenericEnv(nullptr), ThrowsLoc(ThrowsLoc) {
     setBodyKind(BodyKind::None);
     setGenericParams(GenericParams);
     AbstractFunctionDeclBits.NumParameterLists = NumParameterLists;
@@ -4616,6 +4578,15 @@
     return GenericSig;
   }
 
+  /// Retrieve the generic context for this function.
+  GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
+
+  /// Set the generic context of this function.
+  void setGenericEnvironment(GenericEnvironment *GenericEnv) {
+    assert(!this->GenericEnv && "already have generic context?");
+    this->GenericEnv = GenericEnv;
+  }
+
   // Expose our import as member status
   bool isImportAsMember() const { return IAMStatus.isImportAsMember(); }
   bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); }
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 041d4fe..0e8fee9 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -35,6 +35,7 @@
 
 namespace swift {
   class AbstractFunctionDecl;
+  class GenericEnvironment;
   class ASTContext;
   class ASTWalker;
   class CanType;
@@ -284,14 +285,19 @@
   /// type for non-type contexts.
   Type getDeclaredInterfaceType() const;
 
-  /// \brief Retrieve the innermost generic parameters introduced by this
-  /// context or one of its parent contexts, or null if this context is not
-  /// directly dependent on any generic parameters.
+  /// \brief Retrieve the innermost generic parameters of this context or any
+  /// of its parents.
+  ///
+  /// FIXME: Remove this
   GenericParamList *getGenericParamsOfContext() const;
 
-  /// \brief Retrieve the interface generic type parameters and requirements
-  /// exposed by this context.
+  /// \brief Retrieve the innermost generic signature of this context or any
+  /// of its parents.
   GenericSignature *getGenericSignatureOfContext() const;
+
+  /// \brief Retrieve the innermost archetypes of this context or any
+  /// of its parents.
+  GenericEnvironment *getGenericEnvironmentOfContext() const;
   
   /// Returns this or the first local parent context, or nullptr if it is not
   /// contained in one.
diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h
new file mode 100644
index 0000000..14592b4
--- /dev/null
+++ b/include/swift/AST/GenericEnvironment.h
@@ -0,0 +1,77 @@
+//===--- GenericEnvironment.h - Generic Environment AST ---------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the GenericEnvironment class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_AST_GENERIC_ENVIRONMENT_H
+#define SWIFT_AST_GENERIC_ENVIRONMENT_H
+
+#include "swift/AST/ProtocolConformance.h"
+
+namespace swift {
+
+class ASTContext;
+
+/// Describes the mapping between archetypes and interface types for the
+/// generic parameters of a DeclContext.
+class GenericEnvironment final {
+  TypeSubstitutionMap ArchetypeToInterfaceMap;
+  TypeSubstitutionMap InterfaceToArchetypeMap;
+
+public:
+  const TypeSubstitutionMap &getArchetypeToInterfaceMap() const {
+    return ArchetypeToInterfaceMap;
+  }
+
+  const TypeSubstitutionMap &getInterfaceToArchetypeMap() const {
+    return InterfaceToArchetypeMap;
+  }
+
+  explicit GenericEnvironment(TypeSubstitutionMap interfaceToArchetypeMap);
+
+  static GenericEnvironment *get(ASTContext &ctx,
+                                 TypeSubstitutionMap interfaceToArchetypeMap);
+
+  /// Make vanilla new/delete illegal.
+  void *operator new(size_t Bytes) = delete;
+  void operator delete(void *Data) = delete;
+
+  /// Only allow allocation of GenericEnvironments using the allocator
+  /// in ASTContext.
+  void *operator new(size_t bytes, const ASTContext &ctx);
+
+  /// Map a contextual type to an interface type.
+  Type mapTypeOutOfContext(ModuleDecl *M, Type type) const;
+
+  /// Map an interface type to a contextual type.
+  Type mapTypeIntoContext(ModuleDecl *M, Type type) const;
+
+  /// Derive a contextual type substitution map from a substitution array.
+  /// This is just like GenericSignature::getSubstitutionMap(), except
+  /// with contextual types instead of interface types.
+  void
+  getSubstitutionMap(ModuleDecl *mod,
+                     GenericSignature *sig,
+                     ArrayRef<Substitution> subs,
+                     TypeSubstitutionMap &subsMap,
+                     ArchetypeConformanceMap &conformanceMap) const;
+
+  ArrayRef<Substitution>
+  getForwardingSubstitutions(ModuleDecl *M, GenericSignature *sig) const;
+};
+  
+} // end namespace swift
+
+#endif // SWIFT_AST_GENERIC_ENVIRONMENT_H
+
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index 6cd223b..9768dbd 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -184,10 +184,6 @@
   /// Return a range that iterates through first all of the generic parameters
   /// of the signature, followed by all of their recursive member types exposed
   /// through protocol requirements.
-  ///
-  /// The member types are presented in the
-  /// same order as GenericParamList::getAllArchetypes would present for an
-  /// equivalent GenericParamList.
   GenericSignatureWitnessIterator getAllDependentTypes() const {
     return GenericSignatureWitnessIterator(getRequirements());
   }
@@ -204,8 +200,10 @@
   /// for mangling purposes.
   ///
   /// TODO: This is what getCanonicalSignature() ought to do, but currently
-  /// cannot due to implementation dependencies on 'getAllDependentTypes'
-  /// order matching 'getAllArchetypes' order of a generic param list.
+  /// does not due to former implementation dependencies on
+  /// 'getAllDependentTypes' order matching 'getAllArchetypes' order of a
+  /// generic param list. Now that 'getAllArchetypes' is gone, we might
+  /// be able to move forward here.
   CanGenericSignature getCanonicalManglingSignature(ModuleDecl &M) const;
 
   /// Uniquing for the ASTContext.
diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h
index 40047ba..54122e7 100644
--- a/include/swift/AST/PrintOptions.h
+++ b/include/swift/AST/PrintOptions.h
@@ -20,7 +20,7 @@
 #include <vector>
 
 namespace swift {
-class GenericParamList;
+class GenericEnvironment;
 class CanType;
 class Decl;
 class ValueDecl;
@@ -336,9 +336,8 @@
   /// formatting.
   bool PrintOriginalSourceText = false;
 
-  /// \brief Print dependent types as references into this generic parameter
-  /// list.
-  GenericParamList *ContextGenericParams = nullptr;
+  /// \brief Print dependent types as references into this generic environment.
+  GenericEnvironment *GenericEnv = nullptr;
 
   /// \brief Print types with alternative names from their canonical names.
   llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr;
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 23963d2..34e2b87 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -236,10 +236,9 @@
   /// Retrieve the complete set of protocol conformances for directly inherited
   /// protocols.
   const InheritedConformanceMap &getInheritedConformances() const;
-  
+ 
   /// Get the generic parameters open on the conforming type.
-  /// FIXME: Retire in favor of getGenericSignature().
-  GenericParamList *getGenericParams() const;
+  GenericEnvironment *getGenericEnvironment() const;
 
   /// Get the generic signature containing the parameters open on the conforming
   /// interface type.
diff --git a/include/swift/AST/Substitution.h b/include/swift/AST/Substitution.h
index bedcfa9..c5c0717 100644
--- a/include/swift/AST/Substitution.h
+++ b/include/swift/AST/Substitution.h
@@ -26,6 +26,7 @@
 
 namespace swift {
   class ArchetypeType;
+  class GenericEnvironment;
   class ProtocolConformanceRef;
   
 /// DenseMap type used internally by Substitution::subst to track conformances
@@ -63,11 +64,11 @@
   /// conformances.
   ///
   /// Our replacement type must be written in terms of the context
-  /// archetypes of 'context', which in turn must be derived from the
+  /// archetypes of 'env', which in turn must be derived from the
   /// generic requirements of 'sig'.
   Substitution subst(ModuleDecl *module,
                      GenericSignature *sig,
-                     GenericParamList *context,
+                     GenericEnvironment *env,
                      ArrayRef<Substitution> subs) const;
 
 private:
diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h
index c5a0d1e..039b0ce 100644
--- a/include/swift/AST/TypeRepr.h
+++ b/include/swift/AST/TypeRepr.h
@@ -364,9 +364,10 @@
 ///   Foo -> Bar
 /// \endcode
 class FunctionTypeRepr : public TypeRepr {
-  // These two are only used in SIL mode, which is the only time
+  // These three are only used in SIL mode, which is the only time
   // we can have polymorphic function values.
   GenericParamList *GenericParams;
+  GenericEnvironment *GenericEnv;
   GenericSignature *GenericSig;
 
   TypeRepr *ArgsTy;
@@ -378,12 +379,15 @@
   FunctionTypeRepr(GenericParamList *genericParams, TypeRepr *argsTy,
                    SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy)
     : TypeRepr(TypeReprKind::Function),
-      GenericParams(genericParams), GenericSig(nullptr),
+      GenericParams(genericParams),
+      GenericEnv(nullptr),
+      GenericSig(nullptr),
       ArgsTy(argsTy), RetTy(retTy),
       ArrowLoc(arrowLoc), ThrowsLoc(throwsLoc) {
   }
 
   GenericParamList *getGenericParams() const { return GenericParams; }
+  GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
   GenericSignature *getGenericSignature() const { return GenericSig; }
 
   void setGenericSignature(GenericSignature *genericSig) {
@@ -391,6 +395,11 @@
     GenericSig = genericSig;
   }
 
+  void setGenericEnvironment(GenericEnvironment *genericEnv) {
+    assert(GenericEnv == nullptr);
+    GenericEnv = genericEnv;
+  }
+
   TypeRepr *getArgsTypeRepr() const { return ArgsTy; }
   TypeRepr *getResultTypeRepr() const { return RetTy; }
   bool throws() const { return ThrowsLoc.isValid(); }
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 99321e7..ab93ee0 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -92,7 +92,7 @@
   CanSILFunctionType LoweredType;
 
   /// The context archetypes of the function.
-  GenericParamList *ContextGenericParams;
+  GenericEnvironment *GenericEnv;
 
   /// The forwarding substitutions, lazily computed.
   Optional<ArrayRef<Substitution>> ForwardingSubs;
@@ -178,7 +178,7 @@
 
   SILFunction(SILModule &module, SILLinkage linkage,
               StringRef mangledName, CanSILFunctionType loweredType,
-              GenericParamList *contextGenericParams,
+              GenericEnvironment *genericEnv,
               Optional<SILLocation> loc,
               IsBare_t isBareSILFunction,
               IsTransparent_t isTrans,
@@ -192,7 +192,7 @@
 
   static SILFunction *create(SILModule &M, SILLinkage linkage, StringRef name,
                              CanSILFunctionType loweredType,
-                             GenericParamList *contextGenericParams,
+                             GenericEnvironment *genericEnv,
                              Optional<SILLocation> loc,
                              IsBare_t isBareSILFunction,
                              IsTransparent_t isTrans,
@@ -545,16 +545,14 @@
     return (ClangNodeOwner ? ClangNodeOwner->getClangDecl() : nullptr);
   }
 
-  /// Retrieve the generic parameter list containing the contextual archetypes
-  /// of the function.
-  ///
-  /// FIXME: We should remove this in favor of lazy archetype instantiation
-  /// using the 'getArchetype' and 'mapTypeIntoContext' interfaces.
-  GenericParamList *getContextGenericParams() const {
-    return ContextGenericParams;
+  /// Retrieve the generic environment containing the mapping from interface
+  /// types to context archetypes for this function. Only present if the
+  /// function has a body.
+  GenericEnvironment *getGenericEnvironment() const {
+    return GenericEnv;
   }
-  void setContextGenericParams(GenericParamList *params) {
-    ContextGenericParams = params;
+  void setGenericEnvironment(GenericEnvironment *env) {
+    GenericEnv = env;
   }
 
   /// Map the given type, which is based on an interface SILFunctionType and may
diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h
index a5f41f8..cbc9c35 100644
--- a/include/swift/SIL/SILModule.h
+++ b/include/swift/SIL/SILModule.h
@@ -480,7 +480,7 @@
   /// SILModule. Eventually the uses should probably be refactored.
   SILFunction *createFunction(
       SILLinkage linkage, StringRef name, CanSILFunctionType loweredType,
-      GenericParamList *contextGenericParams, Optional<SILLocation> loc,
+      GenericEnvironment *genericEnv, Optional<SILLocation> loc,
       IsBare_t isBareSILFunction, IsTransparent_t isTrans,
       IsFragile_t isFragile, IsThunk_t isThunk = IsNotThunk,
       SILFunction::ClassVisibility_t classVisibility = SILFunction::NotRelevant,
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 368afef..687ab87 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -366,16 +366,9 @@
   /// The SIL function type of the constant.
   CanSILFunctionType SILFnType;
   
-  /// The context generic parameters used by the constant.
-  /// This will be the innermost generic parameter list that applies to the
-  /// constant, which may be the generic parameter list of an enclosing context.
-  GenericParamList *ContextGenericParams;
+  /// The generic environment used by the constant.
+  GenericEnvironment *GenericEnv;
   
-  /// The generic parameter list of the function.
-  /// If the function does not have any generic parameters of its own, this
-  /// will be null.
-  GenericParamList *InnerGenericParams;
-
   SILType getSILType() const {
     return SILType::getPrimitiveObjectType(SILFnType);
   }
@@ -384,8 +377,7 @@
     return lhs.FormalInterfaceType == rhs.FormalInterfaceType &&
            lhs.LoweredInterfaceType == rhs.LoweredInterfaceType &&
            lhs.SILFnType == rhs.SILFnType &&
-           lhs.ContextGenericParams == rhs.ContextGenericParams &&
-           lhs.InnerGenericParams == rhs.InnerGenericParams;
+           lhs.GenericEnv == rhs.GenericEnv;
   }
   friend bool operator!=(SILConstantInfo lhs, SILConstantInfo rhs) {
     return !(lhs == rhs);
@@ -521,11 +513,8 @@
   
   CanAnyFunctionType makeConstantInterfaceType(SILDeclRef constant);
   
-  /// Get the context parameters for a constant. Returns a pair of the innermost
-  /// generic parameter list and the generic param list that directly applies
-  /// to the constant, if any.
-  std::pair<GenericParamList *, GenericParamList*>
-  getConstantContextGenericParams(SILDeclRef constant);
+  /// Get the generic environment for a constant.
+  GenericEnvironment *getConstantGenericEnvironment(SILDeclRef constant);
   
   // Types converted during foreign bridging.
 #define BRIDGING_KNOWN_TYPE(BridgedModule,BridgedType) \
@@ -746,8 +735,8 @@
                                     Type lvalueType);
 
   /// Retrieve the set of archetypes closed over by the given function.
-  GenericParamList *getEffectiveGenericParams(AnyFunctionRef fn,
-                                              CaptureInfo captureInfo);
+  GenericEnvironment *getEffectiveGenericEnvironment(AnyFunctionRef fn,
+                                                     CaptureInfo captureInfo);
 
   /// Retrieve the set of generic parameters closed over by the given function.
   CanGenericSignature getEffectiveGenericSignature(AnyFunctionRef fn,
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index 76ac61c..260704a 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -90,9 +90,9 @@
 
   Substitution remapSubstitution(Substitution sub) {
     if (!ApplySubs.empty()) {
-      auto *params = Original.getContextGenericParams();
       auto sig = Original.getLoweredFunctionType()->getGenericSignature();
-      sub = sub.subst(SwiftMod, sig, params, ApplySubs);
+      auto *env = Original.getGenericEnvironment();
+      sub = sub.subst(SwiftMod, sig, env, ApplySubs);
     }
     // Remap opened archetypes into the cloned context.
     return Substitution(getASTTypeInClonedContext(sub.getReplacement()
@@ -209,9 +209,9 @@
     auto sub = Inst->getSelfSubstitution();
     if (!ApplySubs.empty()) {
       auto sig = Original.getLoweredFunctionType()->getGenericSignature();
-      auto *params = Original.getContextGenericParams();
+      auto *env = Original.getGenericEnvironment();
       sub = sub.subst(Inst->getModule().getSwiftModule(),
-                      sig, params, ApplySubs);
+                      sig, env, ApplySubs);
     }
 
     assert(sub.getConformances().size() == 1 &&
diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def
index 6de1c6d..ff8cdd3 100644
--- a/include/swift/Serialization/DeclTypeRecordNodes.def
+++ b/include/swift/Serialization/DeclTypeRecordNodes.def
@@ -169,6 +169,7 @@
 TRAILING_INFO(GENERIC_PARAM)
 TRAILING_INFO(GENERIC_REQUIREMENT)
 TRAILING_INFO(LAST_GENERIC_REQUIREMENT)
+TRAILING_INFO(GENERIC_ENVIRONMENT)
 
 OTHER(LOCAL_DISCRIMINATOR, 248)
 OTHER(PRIVATE_DISCRIMINATOR, 249)
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index d3aeb00..ba1ef5f 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -426,12 +426,36 @@
   ParameterList *readParameterList();
   
   GenericParamList *maybeGetOrReadGenericParams(serialization::DeclID contextID,
-                                                DeclContext *DC,
-                                                llvm::BitstreamCursor &Cursor);
+                                                DeclContext *DC);
+
+  /// Reads a generic param list from \c DeclTypeCursor.
+  ///
+  /// If the record at the cursor is not a generic param list, returns null
+  /// without moving the cursor.
+  GenericParamList *maybeReadGenericParams(DeclContext *DC,
+                                     GenericParamList *outerParams = nullptr);
 
   /// Reads a set of requirements from \c DeclTypeCursor.
   void readGenericRequirements(SmallVectorImpl<Requirement> &requirements);
 
+  /// Reads a GenericEnvironment from \c DeclTypeCursor.
+  ///
+  /// Also returns the set of generic parameters read, in order, to help with
+  /// forming a GenericSignature.
+  GenericEnvironment *readGenericEnvironment(
+      SmallVectorImpl<GenericTypeParamType *> &paramTypes,
+      llvm::BitstreamCursor &Cursor);
+
+  /// Reads a GenericEnvironment followed by requirements from \c DeclTypeCursor.
+  ///
+  /// Returns the GenericEnvironment and the signature formed from the
+  /// generic parameters of the environment, together with the
+  /// read requirements.
+  ///
+  /// Returns nullptr if there's no generic signature here.
+  std::pair<GenericSignature *, GenericEnvironment *>
+  maybeReadGenericSignature();
+
   /// Populates the vector with members of a DeclContext from \c DeclTypeCursor.
   ///
   /// Returns true if there is an error.
@@ -691,14 +715,6 @@
   NormalProtocolConformance *
   readNormalConformance(serialization::NormalConformanceID id);
 
-  /// Reads a generic param list from \c DeclTypeCursor.
-  ///
-  /// If the record at the cursor is not a generic param list, returns null
-  /// without moving the cursor.
-  GenericParamList *maybeReadGenericParams(DeclContext *DC,
-                                     llvm::BitstreamCursor &Cursor,
-                                     GenericParamList *outerParams = nullptr);
-
   /// Reads a foreign error conformance from \c DeclTypeCursor, if present.
   Optional<ForeignErrorConvention> maybeReadForeignErrorConvention();
 };
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 2585dde..7c58975 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -53,7 +53,7 @@
 /// in source control, you should also update the comment to briefly
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 261; // Last change: remove AllArchetypes indexing
+const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes
 
 using DeclID = PointerEmbeddedInt<unsigned, 31>;
 using DeclIDField = BCFixed<31>;
@@ -1082,8 +1082,7 @@
   >;
 
   using GenericParamListLayout = BCRecordLayout<
-    GENERIC_PARAM_LIST,
-    BCArray<TypeIDField> // Archetypes
+    GENERIC_PARAM_LIST
     // The actual parameters and requirements trail the record.
   >;
 
@@ -1092,6 +1091,24 @@
     DeclIDField // Typealias
   >;
 
+  // Subtlety here: GENERIC_ENVIRONMENT is serialized for both Decls and
+  // SILFunctions.
+  //
+  // For Decls, the interface type is non-canonical, so it points back
+  // to the GenericParamListDecl. This allows us to use the serialized
+  // GENERIC_ENVIRONMENT records to form the GenericSignature, as well.
+  // The type is canonicalized when forming the actual GenericEnvironment
+  // instance.
+  //
+  // For SILFunctions, the interface type below is always canonical,
+  // since SILFunctions never point back to any original
+  // GenericTypeParamDecls.
+  using GenericEnvironmentLayout = BCRecordLayout<
+    GENERIC_ENVIRONMENT,
+    TypeIDField,                 // interface type
+    TypeIDField                  // contextual type
+  >;
+
   using GenericRequirementLayout = BCRecordLayout<
     GENERIC_REQUIREMENT,
     GenericRequirementKindField, // requirement kind
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index 5f0d28e..151bafa 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -43,6 +43,7 @@
   class DiagnosticConsumer;
   class DiagnosticEngine;
   class FileUnit;
+  class GenericEnvironment;
   class GenericParamList;
   class GenericSignature;
   class IRGenOptions;
@@ -208,9 +209,10 @@
                               bool ProduceDiagnostics = true);
 
   /// Expose TypeChecker's handling of GenericParamList to SIL parsing.
-  GenericSignature *handleSILGenericParams(ASTContext &Ctx,
-                                           GenericParamList *genericParams,
-                                           DeclContext *DC);
+  std::pair<GenericSignature *, GenericEnvironment *>
+  handleSILGenericParams(ASTContext &Ctx,
+                         GenericParamList *genericParams,
+                         DeclContext *DC);
 
   /// Turn the given module into SIL IR.
   ///
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7e2c040..c702ee2 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -24,6 +24,7 @@
 #include "swift/AST/DiagnosticsSema.h"
 #include "swift/AST/ExprHandle.h"
 #include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/KnownProtocols.h"
 #include "swift/AST/LazyResolver.h"
 #include "swift/AST/ModuleLoader.h"
@@ -3754,8 +3755,7 @@
 GenericSignature *GenericSignature::get(ArrayRef<GenericTypeParamType *> params,
                                         ArrayRef<Requirement> requirements,
                                         bool isKnownCanonical) {
-  if (params.empty() && requirements.empty())
-    return nullptr;
+  assert(!params.empty());
 
   // Check for an existing generic signature.
   llvm::FoldingSetNodeID ID;
@@ -3781,6 +3781,12 @@
   return newSig;
 }
 
+GenericEnvironment *
+GenericEnvironment::get(ASTContext &ctx,
+                        TypeSubstitutionMap interfaceToArchetypeMap) {
+  return new (ctx) GenericEnvironment(interfaceToArchetypeMap);
+}
+
 void DeclName::CompoundDeclName::Profile(llvm::FoldingSetNodeID &id,
                                          Identifier baseName,
                                          ArrayRef<Identifier> argumentNames) {
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 2905219..88d5310 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -21,6 +21,7 @@
 #include "swift/AST/Attr.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/Expr.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ParameterList.h"
@@ -4274,25 +4275,14 @@
     }
   }
 
-  GenericParamList *getGenericParamListAtDepth(unsigned depth) {
-    assert(Options.ContextGenericParams);
-    if (!UnwrappedGenericParams) {
-      std::vector<GenericParamList *> paramLists;
-      for (auto *params = Options.ContextGenericParams;
-           params;
-           params = params->getOuterParameters()) {
-        paramLists.push_back(params);
-      }
-      UnwrappedGenericParams = std::move(paramLists);
-    }
-    return UnwrappedGenericParams->rbegin()[depth];
-  }
-
   void visitGenericTypeParamType(GenericTypeParamType *T) {
     // Substitute a context archetype if we have context generic params.
-    if (Options.ContextGenericParams) {
-      return visit(getGenericParamListAtDepth(T->getDepth())
-                     ->getParams()[T->getIndex()]->getArchetype());
+    if (Options.GenericEnv) {
+      auto *paramTy = T->getCanonicalType().getPointer();
+      auto &map = Options.GenericEnv->getInterfaceToArchetypeMap();
+      auto found = map.find(paramTy);
+      if (found != map.end())
+        return visit(found->second);
     }
 
     auto Name = T->getName();
@@ -4483,18 +4473,11 @@
 void ProtocolConformance::printName(llvm::raw_ostream &os,
                                     const PrintOptions &PO) const {
   if (getKind() == ProtocolConformanceKind::Normal) {
-    if (PO.PrintForSIL) {
-      if (auto genericSig = getGenericSignature()) {
-        StreamPrinter sPrinter(os);
-        TypePrinter typePrinter(sPrinter, PO);
-        typePrinter.printGenericSignature(genericSig->getGenericParams(),
-                                          genericSig->getRequirements());
-        os << ' ';
-      }
-    } else if (auto gp = getGenericParams()) {
-      StreamPrinter SPrinter(os);
-      PrintAST Printer(SPrinter, PO);
-      Printer.printGenericParams(gp);
+    if (auto genericSig = getGenericSignature()) {
+      StreamPrinter sPrinter(os);
+      TypePrinter typePrinter(sPrinter, PO);
+      typePrinter.printGenericSignature(genericSig->getGenericParams(),
+                                        genericSig->getRequirements());
       os << ' ';
     }
   }
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index f83926c..cc14d5d 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -20,6 +20,7 @@
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Mangle.h"
 #include "swift/AST/PrettyStackTrace.h"
 #include "swift/Basic/SourceManager.h"
@@ -1957,7 +1958,44 @@
         }
       }
     }
-    
+
+    void verifyGenericEnvironment(Decl *D,
+                                  GenericSignature *sig,
+                                  GenericEnvironment *env) {
+      if (!sig && !env)
+        return;
+
+      if (sig && env) {
+        auto &map = env->getInterfaceToArchetypeMap();
+        if (sig->getGenericParams().size() != map.size()) {
+          Out << "Mismatch between signature and environment parameter count\n";
+          abort();
+        }
+
+        for (auto *paramTy : sig->getGenericParams()) {
+          auto found = map.find(paramTy->getCanonicalType().getPointer());
+          if (found == map.end()) {
+            Out << "Generic parameter present in signature but not "
+                   "in environment\n";
+            paramTy->dump();
+            abort();
+          }
+        }
+
+        return;
+      }
+
+      Out << "Decl must have both signature and environment, or neither\n";
+      D->dump(Out);
+      abort();
+    }
+
+    void verifyChecked(GenericTypeDecl *generic) {
+      verifyGenericEnvironment(generic,
+                               generic->getGenericSignature(),
+                               generic->getGenericEnvironment());
+    }
+
     void verifyChecked(NominalTypeDecl *nominal) {
       // Make sure that the protocol list is fully expanded.
       verifyProtocolList(nominal, nominal->getLocalProtocols());
@@ -2084,195 +2122,6 @@
       verifyParsedBase(DD);
     }
 
-    bool checkAllArchetypes(const GenericParamList *generics) {
-      ArrayRef<ArchetypeType*> storedArchetypes = generics->getAllArchetypes();
-
-      SmallVector<ArchetypeType*, 16> derivedBuffer;
-      ArrayRef<ArchetypeType*> derivedArchetypes =
-        GenericParamList::deriveAllArchetypes(generics->getParams(),
-                                              derivedBuffer);
-
-      return (storedArchetypes == derivedArchetypes);
-    }
-
-    /// Check that the generic requirements line up with the archetypes.
-    void checkGenericRequirements(Decl *decl,
-                                  DeclContext *dc,
-                                  GenericFunctionType *genericTy) {
-
-      PrettyStackTraceDecl debugStack("verifying generic requirements", decl);
-
-      // We need to have generic parameters here.
-      auto genericParams = dc->getGenericParamsOfContext();
-      if (!genericParams) {
-        Out << "Missing generic parameters\n";
-        decl->dump(Out);
-        abort();
-      }
-
-      // Verify that the list of all archetypes matches what we would
-      // derive from the generic params.
-      if (!checkAllArchetypes(genericParams)) {
-        Out << "Archetypes list in generic parameter list doesn't "
-               "match what would have been derived\n";
-        decl->dump(Out);
-        abort();
-      }
-
-      // Step through the list of requirements in the generic type.
-      auto requirements = genericTy->getRequirements();
-
-      // Skip over same-type requirements.
-      auto skipUnrepresentedRequirements = [&]() {
-        for (; !requirements.empty(); requirements = requirements.slice(1)) {
-          bool done = false;
-          switch (requirements.front().getKind()) {
-          case RequirementKind::Conformance:
-            // If the second type is a protocol type, we're done.
-            done = true;
-            break;
-
-          case RequirementKind::Superclass:
-            break;
-
-          case RequirementKind::SameType:
-            // Skip the next same-type constraint.
-            continue;
-
-          case RequirementKind::WitnessMarker:
-            done = true;
-            break;
-          }
-
-          if (done)
-            break;
-        }
-      };
-      skipUnrepresentedRequirements();
-
-      // Collect all of the generic parameter lists.
-      SmallVector<GenericParamList *, 4> allGenericParamLists;
-      for (auto gpList = genericParams; gpList;
-           gpList = gpList->getOuterParameters()) {
-        allGenericParamLists.push_back(gpList);
-      }
-      std::reverse(allGenericParamLists.begin(), allGenericParamLists.end());
-
-      // Helpers that diagnose failures when generic requirements mismatch.
-      bool failed = false;
-      auto noteFailure =[&]() {
-        if (failed)
-          return;
-
-        Out << "Generic requirements don't match all archetypes\n";
-        decl->dump(Out);
-
-        Out << "\nGeneric type: " << genericTy->getString() << "\n";
-        Out << "Expected requirements: ";
-        bool first = true;
-        for (auto gpList : allGenericParamLists) {
-          for (auto archetype : gpList->getAllArchetypes()) {
-            for (auto proto : archetype->getConformsTo()) {
-              if (first)
-                first = false;
-              else
-                Out << ", ";
-
-              Out << archetype->getString() << " : "
-                  << proto->getDeclaredType()->getString();
-            }
-          }
-        }
-        Out << "\n";
-
-        failed = true;
-      };
-
-      // Walk through all of the archetypes in the generic parameter lists,
-      // matching up their conformance requirements with those in the
-      for (auto gpList : allGenericParamLists) {
-        for (auto archetype : gpList->getAllArchetypes()) {
-          // Make sure we have the value witness marker.
-          if (requirements.empty()) {
-            noteFailure();
-            Out << "Ran out of requirements before we ran out of archetypes\n";
-            break;
-          }
-
-          if (requirements.front().getKind()
-                == RequirementKind::WitnessMarker) {
-            auto type = ArchetypeBuilder::mapTypeIntoContext(
-                          dc,
-                          requirements.front().getFirstType());
-            if (type->isEqual(archetype)) {
-              requirements = requirements.slice(1);
-              skipUnrepresentedRequirements();
-            } else {
-              noteFailure();
-              Out << "Value witness marker for " << type->getString()
-                  << " does not match expected " << archetype->getString()
-                  << "\n";
-            }
-          } else {
-            noteFailure();
-            Out << "Missing value witness marker for "
-                << archetype->getString() << "\n";
-          }
-
-          for (auto proto : archetype->getConformsTo()) {
-            // If there are no requirements left, we're missing requirements.
-            if (requirements.empty()) {
-              noteFailure();
-              Out << "No requirement for " << archetype->getString()
-                  << " : " << proto->getDeclaredType()->getString() << "\n";
-              continue;
-            }
-
-            auto firstReqType = ArchetypeBuilder::mapTypeIntoContext(
-                                  dc,
-                                  requirements.front().getFirstType());
-            auto secondReqType = ArchetypeBuilder::mapTypeIntoContext(
-                                  dc,
-                                  requirements.front().getSecondType());
-
-            // If the requirements match up, move on to the next requirement.
-            if (firstReqType->isEqual(archetype) &&
-                secondReqType->isEqual(proto->getDeclaredType())) {
-              requirements = requirements.slice(1);
-              skipUnrepresentedRequirements();
-              continue;
-            }
-
-            noteFailure();
-
-            // If the requirements don't match up, complain.
-            if (!firstReqType->isEqual(archetype)) {
-              Out << "Mapped archetype " << firstReqType->getString()
-                  << " does not match expected " << archetype->getString()
-                  << "\n";
-              continue;
-            }
-
-            Out << "Mapped conformance " << secondReqType->getString()
-                << " does not match expected "
-                << proto->getDeclaredType()->getString() << "\n";
-          }
-        }
-      }
-
-      if (!requirements.empty()) {
-        noteFailure();
-        Out << "Extra requirement "
-            << requirements.front().getFirstType()->getString()
-            << " : "
-            << requirements.front().getSecondType()->getString()
-            << "\n";
-      }
-
-      if (failed)
-        abort();
-    }
-
     void verifyChecked(AbstractFunctionDecl *AFD) {
       PrettyStackTraceDecl debugStack("verifying AbstractFunctionDecl", AFD);
 
@@ -2326,6 +2175,10 @@
         abort();
       }
 
+      verifyGenericEnvironment(AFD,
+                               AFD->getGenericSignature(),
+                               AFD->getGenericEnvironment());
+
       // If there is an interface type, it shouldn't have any unresolved
       // dependent member types.
       // FIXME: This is a general property of the type system.
@@ -2347,12 +2200,6 @@
         abort();
       }
 
-      // If the interface type is generic, make sure its requirements
-      // line up with the archetypes.
-      if (auto genericTy = interfaceTy->getAs<GenericFunctionType>()) {
-        checkGenericRequirements(AFD, AFD, genericTy);
-      }
-
       // Throwing @objc methods must have a foreign error convention.
       if (AFD->isObjC() &&
           static_cast<bool>(AFD->getForeignErrorConvention())
diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp
index d468d85..f21f4e6 100644
--- a/lib/AST/ArchetypeBuilder.cpp
+++ b/lib/AST/ArchetypeBuilder.cpp
@@ -20,6 +20,7 @@
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/DiagnosticsSema.h"
 #include "swift/AST/DiagnosticEngine.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/ProtocolConformance.h"
@@ -169,11 +170,6 @@
   /// archetypes.
   llvm::MapVector<GenericTypeParamKey, PotentialArchetype*> PotentialArchetypes;
 
-  /// A vector containing all of the archetypes, expanded out.
-  /// FIXME: This notion should go away, because it's impossible to expand
-  /// out "all" archetypes
-  SmallVector<ArchetypeType *, 4> AllArchetypes;
-
   /// A vector containing the same-type requirements introduced into the
   /// system.
   SmallVector<SameTypeRequirement, 4> SameTypeRequirements;
@@ -1765,41 +1761,6 @@
   return known->second->getType(*this).getAsArchetype();
 }
 
-ArrayRef<ArchetypeType *> ArchetypeBuilder::getAllArchetypes() {
-  // This should be kept in sync with GenericParamList::deriveAllArchetypes().
-  if (Impl->AllArchetypes.empty()) {
-    // Collect the primary archetypes first.
-    unsigned depth = Impl->PotentialArchetypes.back().first.Depth;
-    llvm::SmallPtrSet<ArchetypeType *, 8> KnownArchetypes;
-    for (const auto &Entry : Impl->PotentialArchetypes) {
-      // Skip outer potential archetypes.
-      if (Entry.first.Depth < depth)
-        continue;
-
-      PotentialArchetype *PA = Entry.second;
-      auto Archetype = PA->getType(*this).castToArchetype();
-      if (KnownArchetypes.insert(Archetype).second)
-        Impl->AllArchetypes.push_back(Archetype);
-    }
-
-    // Collect all of the remaining archetypes.
-    for (const auto &Entry : Impl->PotentialArchetypes) {
-      // Skip outer potential archetypes.
-      if (Entry.first.Depth < depth)
-        continue;
-
-      PotentialArchetype *PA = Entry.second;
-      if (!PA->isConcreteType() && !PA->getTypeAliasDecl()) {
-        auto Archetype = PA->getType(*this).castToArchetype();
-        GenericParamList::addNestedArchetypes(Archetype, KnownArchetypes,
-                                              Impl->AllArchetypes);
-      }
-    }
-  }
-
-  return Impl->AllArchetypes;
-}
-
 ArrayRef<ArchetypeBuilder::SameTypeRequirement>
 ArchetypeBuilder::getSameTypeRequirements() const {
   return Impl->SameTypeRequirements;
@@ -2010,88 +1971,44 @@
   out << "\n";
 }
 
-Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type,
-                                          LazyResolver *resolver) {
-  auto genericParams = dc->getGenericParamsOfContext();
-  return mapTypeIntoContext(dc->getParentModule(), genericParams, type,
-                            resolver);
+Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type) {
+  return mapTypeIntoContext(dc->getParentModule(),
+                            dc->getGenericEnvironmentOfContext(),
+                            type);
 }
 
-Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
-                                          GenericParamList *genericParams,
-                                          Type type,
-                                          LazyResolver *resolver) {
+Type ArchetypeBuilder::mapTypeIntoContext(ModuleDecl *M,
+                                          GenericEnvironment *env,
+                                          Type type) {
   auto canType = type->getCanonicalType();
   assert(!canType->hasArchetype() && "already have a contextual type");
   if (!canType->hasTypeParameter())
     return type;
 
-  assert(genericParams && "dependent type in non-generic context");
+  assert(env && "dependent type in non-generic context");
 
-  unsigned genericParamsDepth = genericParams->getDepth();
-  type = type.transform([&](Type type) -> Type {
-    // Map a generic parameter type to its archetype.
-    if (auto gpType = type->getAs<GenericTypeParamType>()) {
-      auto index = gpType->getIndex();
-      unsigned depth = gpType->getDepth();
-
-      // Skip down to the generic parameter list that houses the corresponding
-      // generic parameter.
-      auto myGenericParams = genericParams;
-      assert(genericParamsDepth >= depth);
-      unsigned skipLevels = genericParamsDepth - depth;
-      while (skipLevels > 0) {
-        myGenericParams = myGenericParams->getOuterParameters();
-        assert(myGenericParams && "Wrong number of levels?");
-        --skipLevels;
-      }
-
-      return myGenericParams->getParams()[index]->getArchetype();
-    }
-
-    // Map a dependent member to the corresponding nested archetype.
-    if (auto dependentMember = type->getAs<DependentMemberType>()) {
-      auto base = mapTypeIntoContext(M, genericParams,
-                                     dependentMember->getBase(), resolver);
-      return dependentMember->substBaseType(M, base, resolver);
-    }
-
-    return type;
-  });
-
-  assert(!type->hasTypeParameter() && "not fully substituted");
-  return type;
+  return env->mapTypeIntoContext(M, type);
 }
 
 Type
 ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) {
-  GenericParamList *genericParams = dc->getGenericParamsOfContext();
-  return mapTypeOutOfContext(dc->getParentModule(), genericParams, type);
+  return mapTypeOutOfContext(dc->getParentModule(),
+                             dc->getGenericEnvironmentOfContext(),
+                             type);
 }
 
-Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
-                                           GenericParamList *genericParams,
-                                           Type type) {
+Type
+ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
+                                      GenericEnvironment *env,
+                                      Type type) {
   auto canType = type->getCanonicalType();
   assert(!canType->hasTypeParameter() && "already have an interface type");
   if (!canType->hasArchetype())
     return type;
 
-  assert(genericParams && "dependent type in non-generic context");
+  assert(env && "dependent type in non-generic context");
 
-  // Capture the archetype -> interface type mapping.
-  TypeSubstitutionMap subs;
-  for (auto params = genericParams; params != nullptr;
-       params = params->getOuterParameters()) {
-    for (auto param : *params) {
-      subs[param->getArchetype()] = param->getDeclaredType();
-    }
-  }
-
-  type = type.subst(M, subs, SubstFlags::AllowLoweredTypes);
-
-  assert(!type->hasArchetype() && "not fully substituted");
-  return type;
+  return env->mapTypeOutOfContext(M, type);
 }
 
 void ArchetypeBuilder::addGenericSignature(GenericSignature *sig,
@@ -2213,6 +2130,10 @@
       auto nestedType =
         rep->getDependentType(builder, /*allowUnresolved*/ false);
 
+      // Skip unresolved nested types.
+      if (nestedType->is<ErrorType>())
+        continue;
+
       addRequirements(builder, nestedType, rep, knownPAs, requirements);
       addNestedRequirements(builder, rep, knownPAs, requirements);
     }
@@ -2303,3 +2224,25 @@
   return sig;
 }
 
+GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(
+    ArrayRef<GenericTypeParamType *> genericParamTypes) {
+  TypeSubstitutionMap interfaceToArchetypeMap;
+
+  for (auto paramTy : genericParamTypes) {
+    auto known = Impl->PotentialArchetypes.find(
+                   GenericTypeParamKey::forType(paramTy));
+    assert(known != Impl->PotentialArchetypes.end());
+
+    auto archetypeTy = known->second->getType(*this).getAsArchetype();
+    auto concreteTy = known->second->getType(*this).getAsConcreteType();
+    if (archetypeTy)
+      interfaceToArchetypeMap[paramTy] = archetypeTy;
+    else if (concreteTy)
+      interfaceToArchetypeMap[paramTy] = concreteTy;
+    else
+      llvm_unreachable("broken generic parameter");
+  }
+
+  return GenericEnvironment::get(Context, interfaceToArchetypeMap);
+}
+
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index 6ce7b30..2b04975 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -14,8 +14,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "swift/AST/Builtins.h"
 #include "swift/AST/AST.h"
+#include "swift/AST/Builtins.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/Attributes.h"
@@ -182,7 +183,7 @@
                           Type ResType,
                           Type ResBodyType,
                           GenericParamList *GenericParams,
-                          FunctionType::ExtInfo Info = FunctionType::ExtInfo()){
+                          TypeSubstitutionMap InterfaceToArchetypeMap) {
   assert(GenericParams && "Missing generic parameters");
   auto &Context = ResType->getASTContext();
 
@@ -200,11 +201,13 @@
     requirements.push_back(Requirement(RequirementKind::WitnessMarker,
                                        param, Type()));
   }
-  GenericSignature *Sig = GenericSignature::get(GenericParamTypes,requirements);
-  
-  Type InterfaceType = GenericFunctionType::get(Sig,
-                                                ArgParamType, ResType,
-                                                Info);
+  GenericSignature *Sig =
+      GenericSignature::get(GenericParamTypes, requirements);
+  GenericEnvironment *Env =
+      GenericEnvironment::get(Context, InterfaceToArchetypeMap);
+
+  Type InterfaceType = GenericFunctionType::get(Sig, ArgParamType, ResType,
+                                                AnyFunctionType::ExtInfo());
 
   Module *M = Context.TheBuiltinModule;
   DeclContext *DC = &M->getMainFile(FileUnitKind::Builtin);
@@ -223,7 +226,8 @@
   
   // Compute the function type.
   Type FnType = PolymorphicFunctionType::get(paramList->getType(Context),
-                                             ResBodyType, GenericParams, Info);
+                                             ResBodyType, GenericParams,
+                                             AnyFunctionType::ExtInfo());
   
   DeclName Name(Context, Id, paramList);
   auto func = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(),
@@ -237,6 +241,7 @@
     
   func->setInterfaceType(InterfaceType);
   func->setGenericSignature(Sig);
+  func->setGenericEnvironment(Env);
   func->setImplicit();
   func->setAccessibility(Accessibility::Public);
 
@@ -435,7 +440,7 @@
     new (ctx) GenericTypeParamDecl(&M->getMainFile(FileUnitKind::Builtin),
                                    ident, SourceLoc(), 0, index);
   genericParam->setArchetype(archetype);
-  return { archetype, genericParam };
+  return std::make_pair(archetype, genericParam);
 }
 
 /// Create a generic parameter list with multiple generic parameters.
@@ -444,7 +449,7 @@
                        SmallVectorImpl<ArchetypeType*> &archetypes,
                        SmallVectorImpl<GenericTypeParamDecl*> &genericParams) {
   assert(numParameters <= llvm::array_lengthof(GenericParamNames));
-  assert(archetypes.empty() && genericParams.empty());
+  assert(genericParams.empty());
 
   for (unsigned i = 0; i != numParameters; ++i) {
     auto archetypeAndParam = createGenericParam(ctx, GenericParamNames[i], i);
@@ -454,7 +459,6 @@
 
   auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
                                             SourceLoc());
-  paramList->setAllArchetypes(ctx.AllocateCopy(archetypes));
   return paramList;
 }
 
@@ -469,6 +473,8 @@
     SmallVector<GenericTypeParamDecl*, 2> GenericTypeParams;
     SmallVector<ArchetypeType*, 2> Archetypes;
 
+    TypeSubstitutionMap InterfaceToArchetypeMap;
+
     SmallVector<TupleTypeElt, 4> InterfaceParams;
     SmallVector<Type, 4> BodyParams;
 
@@ -480,6 +486,12 @@
         : Context(ctx) {
       TheGenericParamList = getGenericParams(ctx, numGenericParams,
                                              Archetypes, GenericTypeParams);
+
+      for (unsigned i = 0, e = GenericTypeParams.size(); i < e; i++) {
+        auto paramTy = GenericTypeParams[i]->getDeclaredType()
+            ->getCanonicalType().getPointer();
+        InterfaceToArchetypeMap[paramTy] = Archetypes[i];
+      }
     }
 
     template <class G>
@@ -497,7 +509,8 @@
     ValueDecl *build(Identifier name) {
       return getBuiltinGenericFunction(name, InterfaceParams, BodyParams,
                                        InterfaceResult, BodyResult,
-                                       TheGenericParamList);
+                                       TheGenericParamList,
+                                       InterfaceToArchetypeMap);
     }
 
     // Don't use these generator classes directly; call the make{...}
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 0bd0b85..caf1838 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -21,6 +21,7 @@
   DiagnosticList.cpp
   DocComment.cpp
   Expr.cpp
+  GenericEnvironment.cpp
   GenericSignature.cpp
   Identifier.cpp
   LookupVisibleDecls.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3c2cd9d..e108527 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -536,81 +536,6 @@
   Requirements = newRequirements;
 }
 
-void GenericParamList::
-getForwardingSubstitutionMap(TypeSubstitutionMap &result) const {
-  // Add forwarding substitutions from the outer context if we have
-  // a type nested inside a generic function.
-  for (auto *params = this;
-       params != nullptr;
-       params = params->getOuterParameters()) {
-    for (auto *param : params->getParams())
-      result[param->getDeclaredType()->getCanonicalType().getPointer()]
-          = param->getArchetype();
-  }
-}
-
-ArrayRef<Substitution>
-GenericParamList::getForwardingSubstitutions(GenericSignature *sig) const {
-  // This is stupid. We don't really need a module, because we
-  // should not be looking up concrete conformances when we
-  // substitute types here.
-  auto *mod = getParams()[0]->getDeclContext()->getParentModule();
-
-  TypeSubstitutionMap subs;
-  getForwardingSubstitutionMap(subs);
-
-  auto lookupConformanceFn =
-      [&](Type replacement, ProtocolType *protoType)
-          -> ProtocolConformanceRef {
-    return ProtocolConformanceRef(protoType->getDecl());
-  };
-
-  SmallVector<Substitution, 4> result;
-  sig->getSubstitutions(*mod, subs, lookupConformanceFn, result);
-  return sig->getASTContext().AllocateCopy(result);
-}
-
-/// \brief Add the nested archetypes of the given archetype to the set
-/// of all archetypes.
-void GenericParamList::addNestedArchetypes(ArchetypeType *archetype,
-                                      SmallPtrSetImpl<ArchetypeType*> &known,
-                                      SmallVectorImpl<ArchetypeType*> &all) {
-  for (auto nested : archetype->getNestedTypes()) {
-    auto nestedArch = nested.second.getAsArchetype();
-    if (!nestedArch)
-      continue;
-    if (known.insert(nestedArch).second) {
-      assert(!nestedArch->isPrimary() && "Unexpected primary archetype");
-      all.push_back(nestedArch);
-      addNestedArchetypes(nestedArch, known, all);
-    }
-  }
-}
-
-ArrayRef<ArchetypeType*>
-GenericParamList::deriveAllArchetypes(ArrayRef<GenericTypeParamDecl *> params,
-                                      SmallVectorImpl<ArchetypeType*> &all) {
-  // This should be kept in sync with ArchetypeBuilder::getAllArchetypes().
-
-  assert(all.empty());
-  llvm::SmallPtrSet<ArchetypeType*, 8> known;
-
-  // Collect all the primary archetypes.
-  for (auto param : params) {
-    auto archetype = param->getArchetype();
-    if (known.insert(archetype).second)
-      all.push_back(archetype);
-  }
-
-  // Collect all the nested archetypes.
-  for (auto param : params) {
-    auto archetype = param->getArchetype();
-    addNestedArchetypes(archetype, known, all);
-  }
-
-  return all;
-}
-
 TrailingWhereClause::TrailingWhereClause(
                        SourceLoc whereLoc,
                        ArrayRef<RequirementRepr> requirements)
@@ -818,11 +743,6 @@
   }
 }
 
-void ExtensionDecl::setGenericSignature(GenericSignature *sig) {
-  assert(!GenericSig && "Already have generic signature");
-  GenericSig = sig;
-}
-
 DeclRange ExtensionDecl::getMembers() const {
   loadAllMembers();
   return IterableDeclContext::getMembers();
@@ -2216,11 +2136,6 @@
       Param->setDeclContext(this);
 }
 
-void GenericTypeDecl::setGenericSignature(GenericSignature *sig) {
-  assert(!GenericSig && "Already have generic signature");
-  GenericSig = sig;
-}
-
 
 TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name,
                              SourceLoc NameLoc, TypeLoc UnderlyingTy,
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index abef65f..dcce052 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -257,6 +257,47 @@
   }
 }
 
+GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
+  for (const DeclContext *dc = this; ; dc = dc->getParent()) {
+    switch (dc->getContextKind()) {
+    case DeclContextKind::Module:
+    case DeclContextKind::FileUnit:
+    case DeclContextKind::TopLevelCodeDecl:
+      return nullptr;
+
+    case DeclContextKind::Initializer:
+    case DeclContextKind::SerializedLocal:
+    case DeclContextKind::AbstractClosureExpr:
+    case DeclContextKind::SubscriptDecl:
+      // Closures and initializers can't themselves be generic, but they
+      // can occur in generic contexts.
+      continue;
+
+    case DeclContextKind::AbstractFunctionDecl: {
+      auto *AFD = cast<AbstractFunctionDecl>(dc);
+      if (auto genericCtx = AFD->getGenericEnvironment())
+        return genericCtx;
+      continue;
+    }
+
+    case DeclContextKind::GenericTypeDecl: {
+      auto GTD = cast<GenericTypeDecl>(dc);
+      if (auto genericCtx = GTD->getGenericEnvironment())
+        return genericCtx;
+      continue;
+    }
+
+    case DeclContextKind::ExtensionDecl: {
+      auto ED = cast<ExtensionDecl>(dc);
+      if (auto genericCtx = ED->getGenericEnvironment())
+        return genericCtx;
+      continue;
+    }
+    }
+    llvm_unreachable("bad DeclContextKind");
+  }
+}
+
 DeclContext *DeclContext::getLocalContext() {
   if (isLocalContext())
     return this;
diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp
new file mode 100644
index 0000000..e13b02c
--- /dev/null
+++ b/lib/AST/GenericEnvironment.cpp
@@ -0,0 +1,105 @@
+//===--- GenericEnvironment.h - GenericEnvironment AST --------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the GenericEnvironment class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/GenericEnvironment.h"
+
+using namespace swift;
+
+GenericEnvironment::GenericEnvironment(
+    TypeSubstitutionMap interfaceToArchetypeMap) {
+
+  assert(!interfaceToArchetypeMap.empty());
+
+  // Build a mapping in both directions, making sure to canonicalize the
+  // interface type where it is used as a key, so that substitution can
+  // find them, and to preserve sugar otherwise, so that
+  // mapTypeOutOfContext() produces a human-readable type.
+  for (auto entry : interfaceToArchetypeMap) {
+    // We're going to pass InterfaceToArchetypeMap to Type::subst(), which
+    // expects the keys to be canonical, otherwise it won't be able to
+    // find them.
+    auto canParamTy = cast<GenericTypeParamType>(entry.first->getCanonicalType());
+    auto contextTy = entry.second;
+
+    auto result = InterfaceToArchetypeMap.insert(
+        std::make_pair(canParamTy, contextTy));
+    assert(result.second && "duplicate generic parameters in environment");
+
+    // If we mapped the generic parameter to an archetype, add it to the
+    // reverse mapping.
+    if (auto *archetypeTy = entry.second->getAs<ArchetypeType>())
+      ArchetypeToInterfaceMap[archetypeTy] = entry.first;
+
+    // FIXME: If multiple generic parameters map to the same archetype,
+    // the reverse mapping order is not deterministic.
+  }
+}
+
+void *GenericEnvironment::operator new(size_t bytes, const ASTContext &ctx) {
+  return ctx.Allocate(bytes, alignof(GenericEnvironment), AllocationArena::Permanent);
+}
+
+Type GenericEnvironment::mapTypeOutOfContext(ModuleDecl *M, Type type) const {
+  type = type.subst(M, ArchetypeToInterfaceMap, SubstFlags::AllowLoweredTypes);
+  assert(!type->hasArchetype() && "not fully substituted");
+  return type;
+}
+
+Type GenericEnvironment::mapTypeIntoContext(ModuleDecl *M, Type type) const {
+  type = type.subst(M, InterfaceToArchetypeMap, SubstFlags::AllowLoweredTypes);
+  assert(!type->hasTypeParameter() && "not fully substituted");
+  return type;
+}
+
+ArrayRef<Substitution>
+GenericEnvironment::getForwardingSubstitutions(
+    ModuleDecl *M, GenericSignature *sig) const {
+  auto lookupConformanceFn =
+      [&](Type replacement, ProtocolType *protoType)
+          -> ProtocolConformanceRef {
+    return ProtocolConformanceRef(protoType->getDecl());
+  };
+
+  SmallVector<Substitution, 4> result;
+  sig->getSubstitutions(*M, InterfaceToArchetypeMap,
+                        lookupConformanceFn, result);
+  return sig->getASTContext().AllocateCopy(result);
+}
+
+void GenericEnvironment::
+getSubstitutionMap(ModuleDecl *mod,
+                   GenericSignature *sig,
+                   ArrayRef<Substitution> subs,
+                   TypeSubstitutionMap &subsMap,
+                   ArchetypeConformanceMap &conformanceMap) const {
+
+  for (auto depTy : sig->getAllDependentTypes()) {
+
+    // Map the interface type to a context type.
+    auto contextTy = depTy.subst(mod, InterfaceToArchetypeMap, SubstOptions());
+    auto *archetype = contextTy->castTo<ArchetypeType>();
+
+    auto sub = subs.front();
+    subs = subs.slice(1);
+
+    // Record the replacement type and its conformances.
+    subsMap[archetype] = sub.getReplacement();
+    conformanceMap[archetype] = sub.getConformances();
+  }
+  
+  assert(subs.empty() && "did not use all substitutions?!");
+}
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 09c5395..b3d85ae 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -13,11 +13,13 @@
 // This file implements the GenericSignature class.
 //
 //===----------------------------------------------------------------------===//
+
 #include "swift/AST/GenericSignature.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/Types.h"
+
 using namespace swift;
 
 GenericSignature::GenericSignature(ArrayRef<GenericTypeParamType *> params,
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 1cb1331..5f94d05 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -19,6 +19,7 @@
 #include "swift/AST/ASTPrinter.h"
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/DiagnosticsSema.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/LazyResolver.h"
 #include "swift/AST/LinkLibrary.h"
 #include "swift/AST/ModuleLoader.h"
@@ -587,16 +588,15 @@
   auto *parentDC = gpContext;
   while (parent) {
     if (auto boundGeneric = dyn_cast<BoundGenericType>(parent)) {
-      auto genericParams = parentDC->getGenericParamsOfContext();
+      auto genericSig = parentDC->getGenericSignatureOfContext();
       unsigned index = 0;
 
       assert(boundGeneric->getGenericArgs().size() ==
-             genericParams->getParams().size());
+             genericSig->getInnermostGenericParams().size());
 
       for (Type arg : boundGeneric->getGenericArgs()) {
-        auto gp = genericParams->getParams()[index++];
-        substitutions[gp->getDeclaredType()->getCanonicalType()
-                        .getPointer()] = arg;
+        auto paramTy = genericSig->getInnermostGenericParams()[index++];
+        substitutions[paramTy->getCanonicalType().getPointer()] = arg;
       }
 
       parent = CanType(boundGeneric->getParent());
@@ -615,8 +615,11 @@
 
   // Add forwarding substitutions from the outer context if we have
   // a type nested inside a generic function.
-  if (auto *outerParams = parentDC->getGenericParamsOfContext())
-    outerParams->getForwardingSubstitutionMap(substitutions);
+  if (auto *outerEnv = parentDC->getGenericEnvironmentOfContext())
+    for (auto pair : outerEnv->getInterfaceToArchetypeMap()) {
+      auto result = substitutions.insert(pair);
+      assert(result.second);
+    }
 
   auto lookupConformanceFn =
       [&](Type replacement, ProtocolType *protoType)
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index c9083f2..37555cf 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -18,6 +18,7 @@
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/LazyResolver.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/AST/Substitution.h"
@@ -180,18 +181,20 @@
   CONFORMANCE_SUBCLASS_DISPATCH(usesDefaultDefinition, (requirement))
 }
 
-GenericParamList *ProtocolConformance::getGenericParams() const {
+GenericEnvironment *ProtocolConformance::getGenericEnvironment() const {
   switch (getKind()) {
   case ProtocolConformanceKind::Inherited:
   case ProtocolConformanceKind::Normal:
     // If we have a normal or inherited protocol conformance, look for its
     // generic parameters.
-    return getDeclContext()->getGenericParamsOfContext();
+    return getDeclContext()->getGenericEnvironmentOfContext();
 
   case ProtocolConformanceKind::Specialized:
     // If we have a specialized protocol conformance, since we do not support
     // currently partial specialization, we know that it cannot have any open
     // type variables.
+    //
+    // FIXME: We could return a meaningful GenericEnvironment here
     return nullptr;
   }
 }
@@ -354,7 +357,7 @@
   auto conformingDC = getDeclContext();
   auto conformingModule = conformingDC->getParentModule();
 
-  auto *genericParams = GenericConformance->getGenericParams();
+  auto *genericEnv = GenericConformance->getGenericEnvironment();
   auto *genericSig = GenericConformance->getGenericSignature();
 
   TypeSubstitutionMap substitutionMap;
@@ -366,10 +369,10 @@
 
   // Compute a context type substitution map from the
   // substitution array stored in this conformance
-  genericParams->getSubstitutionMap(conformingModule, genericSig,
-                                    GenericSubstitutions,
-                                    substitutionMap,
-                                    conformanceMap);
+  genericEnv->getSubstitutionMap(conformingModule, genericSig,
+                                 GenericSubstitutions,
+                                 substitutionMap,
+                                 conformanceMap);
 
   auto genericWitnessAndDecl
     = GenericConformance->getTypeWitnessSubstAndDecl(assocType, resolver);
@@ -523,10 +526,10 @@
     auto *conformingModule = conformingDC->getParentModule();
 
     auto *sig = conformingDC->getGenericSignatureOfContext();
-    auto *params = conformingDC->getGenericParamsOfContext();
+    auto *env = conformingDC->getGenericEnvironmentOfContext();
 
-    params->getSubstitutionMap(conformingModule, sig, subs,
-                               subMap, conformanceMap);
+    env->getSubstitutionMap(conformingModule, sig, subs,
+                            subMap, conformanceMap);
 
     auto r = inherited->subst(conformingModule, getType(), subs,
                               subMap, conformanceMap);
diff --git a/lib/AST/Substitution.cpp b/lib/AST/Substitution.cpp
index 598c57f..2e2b92b2 100644
--- a/lib/AST/Substitution.cpp
+++ b/lib/AST/Substitution.cpp
@@ -17,6 +17,7 @@
 #include "swift/AST/Substitution.h"
 
 #include "swift/AST/ASTContext.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/Types.h"
 #include "llvm/ADT/DenseMap.h"
@@ -42,13 +43,13 @@
 
 Substitution Substitution::subst(Module *module,
                                  GenericSignature *sig,
-                                 GenericParamList *context,
+                                 GenericEnvironment *env,
                                  ArrayRef<Substitution> subs) const {
   TypeSubstitutionMap subMap;
   ArchetypeConformanceMap conformanceMap;
 
-  assert(sig && context);
-  context->getSubstitutionMap(module, sig, subs, subMap, conformanceMap);
+  assert(sig && env);
+  env->getSubstitutionMap(module, sig, subs, subMap, conformanceMap);
   return subst(module, subs, subMap, conformanceMap);
 }
 
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e10a0be..9706fab 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2767,34 +2767,6 @@
   return Params->getParams();
 }
 
-void GenericParamList::
-getSubstitutionMap(ModuleDecl *mod,
-                   GenericSignature *sig,
-                   ArrayRef<Substitution> subs,
-                   TypeSubstitutionMap &subsMap,
-                   ArchetypeConformanceMap &conformanceMap) const {
-
-  // Map from interface types to archetypes
-  TypeSubstitutionMap map;
-  getForwardingSubstitutionMap(map);
-
-  for (auto depTy : sig->getAllDependentTypes()) {
-
-    // Map the interface type to a context type.
-    auto contextTy = depTy.subst(mod, map, SubstOptions());
-    auto *archetype = contextTy->castTo<ArchetypeType>();
-
-    auto sub = subs.front();
-    subs = subs.slice(1);
-
-    // Record the replacement type and its conformances.
-    subsMap[archetype] = sub.getReplacement();
-    conformanceMap[archetype] = sub.getConformances();
-  }
-  
-  assert(subs.empty() && "did not use all substitutions?!");
-}
-
 FunctionType *
 GenericFunctionType::substGenericArgs(Module *M, ArrayRef<Substitution> args) {
   auto params = getGenericParams();
@@ -3489,8 +3461,6 @@
         anyChanges = true;
     }
     
-    auto sig = GenericSignature::get(genericParams, requirements);
-
     // Transform input type.
     auto inputTy = function->getInput().transform(fn);
     if (!inputTy)
@@ -3508,11 +3478,12 @@
       return *this;
 
     // If no generic parameters remain, this is a non-generic function type.
-    if (genericParams.empty())
+    if (genericParams.empty()) {
       return FunctionType::get(inputTy, resultTy, function->getExtInfo());
+    }
 
     // Produce the new generic function type.
-    
+    auto sig = GenericSignature::get(genericParams, requirements);
     return GenericFunctionType::get(sig, inputTy, resultTy,
                                     function->getExtInfo());
   }
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index ab6dab4..e5added 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -23,6 +23,8 @@
 #include "swift/AST/Decl.h"
 #include "swift/AST/DiagnosticsClangImporter.h"
 #include "swift/AST/Expr.h"
+#include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/GenericSignature.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ParameterList.h"
@@ -1365,12 +1367,14 @@
       // Handle generic types.
       GenericParamList *genericParams = nullptr;
       GenericSignature *genericSig = nullptr;
+      GenericEnvironment *genericEnv = nullptr;
       auto underlyingType = typeDecl->getDeclaredInterfaceType();
 
       if (auto generic = dyn_cast<GenericTypeDecl>(typeDecl)) {
         if (generic->getGenericSignature() && !isa<ProtocolDecl>(typeDecl)) {
           genericParams = generic->getGenericParams();
           genericSig = generic->getGenericSignature();
+          genericEnv = generic->getGenericEnvironment();
 
           underlyingType = ArchetypeBuilder::mapTypeIntoContext(
               generic, underlyingType);
@@ -1395,6 +1399,7 @@
                      genericParams, dc);
       alias->computeType();
       alias->setGenericSignature(genericSig);
+      alias->setGenericEnvironment(genericEnv);
 
       // Record that this is the Swift 2 version of this declaration.
       Impl.ImportedDecls[{decl->getCanonicalDecl(), true}] = alias;
@@ -3133,6 +3138,7 @@
       result->setType(fnType);
       result->setInterfaceType(interfaceType);
       result->setGenericSignature(dc->getGenericSignatureOfContext());
+      result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
 
       result->setBodyResultType(swiftResultTy);
       result->setAccessibility(Accessibility::Public);
@@ -3912,6 +3918,7 @@
       result->setType(type);
       result->setInterfaceType(interfaceType);
       result->setGenericSignature(dc->getGenericSignatureOfContext());
+      result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
 
       // Optional methods in protocols.
       if (decl->getImplementationControl() == clang::ObjCMethodDecl::Optional &&
@@ -4386,6 +4393,7 @@
       result->setInitializerInterfaceType(interfaceInitType);
       result->setInterfaceType(interfaceAllocType);
       result->setGenericSignature(dc->getGenericSignatureOfContext());
+      result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
 
       result->setType(allocType);
 
@@ -4523,6 +4531,8 @@
       thunk->setBodyResultType(elementTy);
       thunk->setInterfaceType(interfaceType);
       thunk->setGenericSignature(dc->getGenericSignatureOfContext());
+      thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
+
       thunk->setAccessibility(getOverridableAccessibility(dc));
 
       auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>();
@@ -4594,6 +4604,8 @@
       thunk->setBodyResultType(TupleType::getEmpty(C));
       thunk->setInterfaceType(interfaceType);
       thunk->setGenericSignature(dc->getGenericSignatureOfContext());
+      thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
+
       thunk->setAccessibility(getOverridableAccessibility(dc));
 
       auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>();
@@ -5143,22 +5155,24 @@
             Impl.importSourceLoc(typeParamList->getRAngleLoc()));
     }
 
-    // Calculate the generic signature for the given imported generic param
-    // list. If there are any errors in doing so, return 'nullptr'.
-    GenericSignature *calculateGenericSignature(GenericParamList *genericParams,
-                                                DeclContext *dc) {
+    // Calculate the generic signature and interface type to archetype mapping
+    // from an imported generic param list.
+    std::pair<GenericSignature *, GenericEnvironment *>
+    calculateGenericSignature(GenericParamList *genericParams,
+                              DeclContext *dc) {
       ArchetypeBuilder builder(*dc->getParentModule(), Impl.SwiftContext.Diags);
       for (auto param : *genericParams)
         builder.addGenericParameter(param);
       for (auto param : *genericParams) {
-        if (builder.addGenericParameterRequirements(param)) {
-          return nullptr;
-        }
+        bool result = builder.addGenericParameterRequirements(param);
+        assert(!result);
+        (void) result;
       }
       // TODO: any need to infer requirements?
-      if (builder.finalize(genericParams->getSourceRange().Start)) {
-        return nullptr;
-      }
+      bool result = builder.finalize(genericParams->getSourceRange().Start);
+      assert(!result);
+      (void) result;
+
       SmallVector<GenericTypeParamType *, 4> genericParamTypes;
       for (auto param : *genericParams) {
         genericParamTypes.push_back(
@@ -5166,10 +5180,11 @@
         auto *archetype = builder.getArchetype(param);
         param->setArchetype(archetype);
       }
-      genericParams->setAllArchetypes(
-          Impl.SwiftContext.AllocateCopy(builder.getAllArchetypes()));
 
-      return builder.getGenericSignature(genericParamTypes);
+      auto *sig = builder.getGenericSignature(genericParamTypes);
+      auto *env = builder.getGenericEnvironment(genericParamTypes);
+
+      return std::make_pair(sig, env);
     }
 
     /// Import members of the given Objective-C container and add them to the
@@ -5507,11 +5522,14 @@
         auto genericParams = GenericParamList::create(Impl.SwiftContext,
             SourceLoc(), toGenericParams, SourceLoc());
         result->setGenericParams(genericParams);
-        if (auto sig = calculateGenericSignature(genericParams, result)) {
-          result->setGenericSignature(sig);
-        } else {
-          return nullptr;
-        }
+
+        GenericSignature *sig;
+        GenericEnvironment *env;
+        std::tie(sig, env) = calculateGenericSignature(genericParams, result);
+
+        result->setGenericSignature(sig);
+        result->setGenericEnvironment(env);
+
         // Calculate the correct bound-generic extended type.
         SmallVector<Type, 2> genericArgs;
         for (auto gp : *genericParams) {
@@ -5669,12 +5687,6 @@
                                                  Type(result->getDeclaredType()),
                                                  Type(), false);
       selfDecl->setArchetype(selfArchetype);
-
-      // Set AllArchetypes of the protocol. ObjC protocols don't have associated
-      // types so only the Self archetype is present.
-      
-      result->getGenericParams()->setAllArchetypes(
-             Impl.SwiftContext.AllocateCopy(llvm::makeArrayRef(selfArchetype)));
       
       // Set the generic parameters and requirements.
       auto genericParam = selfDecl->getDeclaredType()
@@ -5687,6 +5699,15 @@
       auto sig = GenericSignature::get(genericParam, genericRequirements);
       result->setGenericSignature(sig);
 
+      TypeSubstitutionMap interfaceToArchetypeMap;
+
+      auto paramTy = selfDecl->getDeclaredType()->getCanonicalType();
+      interfaceToArchetypeMap[paramTy.getPointer()] = selfArchetype;
+
+      auto *env =
+          GenericEnvironment::get(Impl.SwiftContext, interfaceToArchetypeMap);
+      result->setGenericEnvironment(env);
+
       result->setCircularityCheck(CircularityCheck::Checked);
 
       // Import protocols this protocol conforms to.
@@ -5818,11 +5839,13 @@
         auto genericParams = *gpImportResult;
         if (genericParams) {
           result->setGenericParams(genericParams);
-          if (auto sig = calculateGenericSignature(genericParams, result)) {
-            result->setGenericSignature(sig);
-          } else {
-            return nullptr;
-          }
+
+          GenericSignature *sig;
+          GenericEnvironment *env;
+          std::tie(sig, env) = calculateGenericSignature(genericParams, result);
+
+          result->setGenericSignature(sig);
+          result->setGenericEnvironment(env);
         }
       } else {
         return nullptr;
@@ -6967,8 +6990,6 @@
         conformsTo, protoArchetype->getSuperclass(),
         protoArchetype->getIsRecursive());
     extSelf->setArchetype(extSelfArchetype);
-    ext->getGenericParams()->setAllArchetypes(
-        SwiftContext.AllocateCopy(llvm::makeArrayRef(extSelfArchetype)));
 
     auto genericParam =
         extSelf->getDeclaredType()->castTo<GenericTypeParamType>();
@@ -6976,8 +6997,17 @@
         Requirement(RequirementKind::WitnessMarker, genericParam, Type()),
         Requirement(RequirementKind::Conformance, genericParam,
                     protoDecl->getDeclaredType())};
-    auto sig = GenericSignature::get(genericParam, genericRequirements);
+    auto *sig = GenericSignature::get(genericParam, genericRequirements);
     ext->setGenericSignature(sig);
+
+    TypeSubstitutionMap interfaceToArchetypeMap;
+
+    auto paramTy = extSelf->getDeclaredType()->getCanonicalType();
+    interfaceToArchetypeMap[paramTy.getPointer()] = extSelfArchetype;
+
+    auto *env =
+        GenericEnvironment::get(SwiftContext, interfaceToArchetypeMap);
+    ext->setGenericEnvironment(env);
   }
 
   // Add the extension to the nominal type.
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 3333be2..8d9a5db 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -236,7 +236,7 @@
   array = IGF.Builder.CreateElementBitCast(array, IGF.IGM.TypeMetadataPtrTy);
 
   auto getInContext = [&](CanType type) -> CanType {
-    return ArchetypeBuilder::mapTypeIntoContext(typeDecl, type, nullptr)
+    return ArchetypeBuilder::mapTypeIntoContext(typeDecl, type)
              ->getCanonicalType();
   };
 
@@ -2767,7 +2767,7 @@
     auto declCtxt = type;
     if (auto generics = declCtxt->getGenericSignatureOfContext()) {
       auto getInContext = [&](CanType type) -> CanType {
-        return ArchetypeBuilder::mapTypeIntoContext(declCtxt, type, nullptr)
+        return ArchetypeBuilder::mapTypeIntoContext(declCtxt, type)
             ->getCanonicalType();
       };
       bindArchetypeAccessPaths(IGF, generics, getInContext);
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 5da8cb1..1c93bf6 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1281,7 +1281,7 @@
       auto declCtx = Conformance.getDeclContext();
       if (auto generics = declCtx->getGenericSignatureOfContext()) {
         auto getInContext = [&](CanType type) -> CanType {
-          return ArchetypeBuilder::mapTypeIntoContext(declCtx, type, nullptr)
+          return ArchetypeBuilder::mapTypeIntoContext(declCtx, type)
               ->getCanonicalType();
         };
         bindArchetypeAccessPaths(IGF, generics, getInContext);
diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp
index fa2bee0..c8dc4a6 100644
--- a/lib/Parse/ParseSIL.cpp
+++ b/lib/Parse/ParseSIL.cpp
@@ -13,6 +13,7 @@
 #include "swift/Basic/Defer.h"
 #include "swift/Basic/Fallthrough.h"
 #include "swift/AST/ArchetypeBuilder.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/Parse/Parser.h"
 #include "swift/Parse/Lexer.h"
@@ -213,12 +214,14 @@
     bool parseASTType(CanType &result);
     bool parseSILType(SILType &Result,
                       GenericSignature *&genericSig,
+                      GenericEnvironment *&genericEnv,
                       GenericParamList *&genericParams,
                       bool IsFuncDecl = false);
     bool parseSILType(SILType &Result) {
       GenericSignature *IgnoredSig;
+      GenericEnvironment *IgnoredEnv;
       GenericParamList *IgnoredParams;
-      return parseSILType(Result, IgnoredSig, IgnoredParams);
+      return parseSILType(Result, IgnoredSig, IgnoredEnv, IgnoredParams);
     }
     bool parseSILType(SILType &Result, SourceLoc &TypeLoc) {
       TypeLoc = P.Tok.getLoc();
@@ -226,9 +229,10 @@
     }
     bool parseSILType(SILType &Result, SourceLoc &TypeLoc,
                       GenericSignature *&GenericSig,
+                      GenericEnvironment *&GenericEnv,
                       GenericParamList *&GenericParams) {
       TypeLoc = P.Tok.getLoc();
-      return parseSILType(Result, GenericSig, GenericParams);
+      return parseSILType(Result, GenericSig, GenericEnv, GenericParams);
     }
 
     /// Parse a SIL type without the leading '$' or value category specifier.
@@ -236,15 +240,18 @@
                                        SILValueCategory category,
                                        const TypeAttributes &attrs,
                                        GenericSignature *&genericSig,
+                                       GenericEnvironment *&genericEnv,
                                        GenericParamList *&genericParams,
                                        bool IsFuncDecl = false);
     bool parseSILTypeWithoutQualifiers(SILType &Result,
                                        SILValueCategory category,
                                        const TypeAttributes &attrs) {
       GenericSignature *IgnoredSig;
+      GenericEnvironment *IgnoredEnv;
       GenericParamList *IgnoredParams;
       return parseSILTypeWithoutQualifiers(Result, category, attrs,
-                                           IgnoredSig, IgnoredParams);
+                                           IgnoredSig, IgnoredEnv,
+                                           IgnoredParams);
     }
 
     bool parseSILDottedPath(ValueDecl *&Decl,
@@ -305,13 +312,15 @@
 
     ProtocolConformance *parseProtocolConformance(ProtocolDecl *&proto,
                              GenericSignature *&genericSig,
+                             GenericEnvironment *&genericEnv,
                              GenericParamList *&genericParams,
                              bool localScope);
     ProtocolConformance *parseProtocolConformance() {
       ProtocolDecl *dummy;
       GenericSignature *sig;
+      GenericEnvironment *env;
       GenericParamList *gp;
-      return parseProtocolConformance(dummy, sig, gp, true);
+      return parseProtocolConformance(dummy, sig, env, gp, true);
     }
 
     Optional<llvm::coverage::Counter>
@@ -838,9 +847,11 @@
                                               SILValueCategory category,
                                               const TypeAttributes &attrs,
                                               GenericSignature *&GenericSig,
+                                              GenericEnvironment *&GenericEnv,
                                               GenericParamList *&GenericParams,
                                               bool IsFuncDecl){
   GenericSig = nullptr;
+  GenericEnv = nullptr;
   GenericParams = nullptr;
 
   // If this is part of a function decl, generic parameters are visible in the
@@ -862,8 +873,10 @@
     if (auto generics = fnType->getGenericParams()) {
       GenericParams = generics;
 
-      GenericSig = handleSILGenericParams(P.Context, generics, &P.SF);
+      std::tie(GenericSig, GenericEnv) =
+          handleSILGenericParams(P.Context, generics, &P.SF);
       fnType->setGenericSignature(GenericSig);
+      fnType->setGenericEnvironment(GenericEnv);
     }
   }
   
@@ -888,9 +901,11 @@
 ///
 bool SILParser::parseSILType(SILType &Result,
                              GenericSignature *&GenericSig,
+                             GenericEnvironment *&GenericEnv,
                              GenericParamList *&GenericParams,
                              bool IsFuncDecl){
   GenericSig = nullptr;
+  GenericEnv = nullptr;
   GenericParams = nullptr;
 
   if (P.parseToken(tok::sil_dollar, diag::expected_sil_type))
@@ -914,7 +929,7 @@
     attrs.convention = "thin";
   }
   return parseSILTypeWithoutQualifiers(Result, category, attrs,
-                                       GenericSig, GenericParams,
+                                       GenericSig, GenericEnv, GenericParams,
                                        IsFuncDecl);
 }
 
@@ -1479,20 +1494,22 @@
 /// from a SILFunctionType.
 bool getApplySubstitutionsFromParsed(
                              SILParser &SP,
-                             GenericSignature *sig,
                              GenericParamList *params,
+                             GenericSignature *sig,
+                             GenericEnvironment *env,
                              ArrayRef<ParsedSubstitution> parses,
                              SmallVectorImpl<Substitution> &subs) {
   if (parses.empty()) {
-    assert (!sig && !params);
+    assert (!sig && !env);
     return false;
   }
 
-  assert(sig && params);
+  assert(sig && env);
+
+  auto loc = params->getRAngleLoc();
 
   // Map from interface types to archetypes
-  TypeSubstitutionMap map;
-  params->getForwardingSubstitutionMap(map);
+  TypeSubstitutionMap map = env->getInterfaceToArchetypeMap();
 
   auto *mod = SP.SILMod.getSwiftModule();
 
@@ -1504,7 +1521,7 @@
     auto *archetype = contextTy->castTo<ArchetypeType>();
 
     if (parses.empty()) {
-      SP.P.diagnose(params->getRAngleLoc(), diag::sil_missing_substitutions);
+      SP.P.diagnose(loc, diag::sil_missing_substitutions);
       return true;
     }
     auto parsed = parses.front();
@@ -1520,7 +1537,7 @@
                     SP.P.Context.AllocateCopy(conformances)});
   }
   if (!parses.empty()) {
-    SP.P.diagnose(params->getRAngleLoc(), diag::sil_too_many_substitutions);
+    SP.P.diagnose(loc, diag::sil_too_many_substitutions);
     return true;
   }
   return false;
@@ -1882,6 +1899,7 @@
 
     auto *builtinFunc = cast<FuncDecl>(foundBuiltins[0]);
     GenericSignature *genericSig = builtinFunc->getGenericSignature();
+    GenericEnvironment *genericEnv = builtinFunc->getGenericEnvironment();
     GenericParamList *genericParams = builtinFunc->getGenericParams();
     
     SmallVector<ParsedSubstitution, 4> parsedSubs;
@@ -1894,7 +1912,10 @@
         P.diagnose(P.Tok, diag::sil_substitutions_on_non_polymorphic_type);
         return true;
       }
-      if (getApplySubstitutionsFromParsed(*this, genericSig, genericParams,
+      if (getApplySubstitutionsFromParsed(*this,
+                                          genericParams,
+                                          genericSig,
+                                          genericEnv,
                                           parsedSubs, subs))
         return true;
     }
@@ -2381,6 +2402,7 @@
                                        ParsedSetterSubs;
     GenericSignature *InitStorageSig, *SetterSig;
     GenericParamList *InitStorageParams, *SetterParams;
+    GenericEnvironment *InitStorageEnv, *SetterEnv;
     SILType InitStorageTy, SetterTy;
     
     // mark_uninitialized_behavior %init<Subs>(%storage) : $T -> U,
@@ -2391,7 +2413,7 @@
         || parseValueName(StorageName)
         || P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")")
         || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
-        || parseSILType(InitStorageTy, InitStorageSig, InitStorageParams)
+        || parseSILType(InitStorageTy, InitStorageSig, InitStorageEnv, InitStorageParams)
         || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",")
         || parseValueName(SetterFuncName)
         || parseApplySubstitutions(ParsedSetterSubs)
@@ -2399,7 +2421,7 @@
         || parseValueName(SelfName)
         || P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")")
         || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
-        || parseSILType(SetterTy, SetterSig, SetterParams))
+        || parseSILType(SetterTy, SetterSig, SetterEnv, SetterParams))
       return true;
     
     // Resolve the types of the operands.
@@ -2409,9 +2431,12 @@
     
     SmallVector<Substitution, 4> InitStorageSubs, SetterSubs;
     if (getApplySubstitutionsFromParsed(*this,
-                                        InitStorageSig, InitStorageParams,
+                                        InitStorageParams,
+                                        InitStorageSig, InitStorageEnv,
                                         ParsedInitStorageSubs, InitStorageSubs)
-        || getApplySubstitutionsFromParsed(*this, SetterSig, SetterParams,
+        || getApplySubstitutionsFromParsed(*this,
+                                           SetterParams,
+                                           SetterSig, SetterEnv,
                                            ParsedSetterSubs, SetterSubs))
       return true;
     
@@ -2913,8 +2938,12 @@
       if (auto generics = fnType->getGenericParams()) {
         assert(!Ty.wasValidated() && Ty.getType().isNull());
 
-        auto *genericSig = handleSILGenericParams(P.Context, generics, &P.SF);
+        GenericSignature *genericSig;
+        GenericEnvironment *genericEnv;
+        std::tie(genericSig, genericEnv) =
+            handleSILGenericParams(P.Context, generics, &P.SF);
         fnType->setGenericSignature(genericSig);
+        fnType->setGenericEnvironment(genericEnv);
       }
     }
 
@@ -3615,6 +3644,7 @@
     UnresolvedValueName invokeName;
     SILType invokeTy;
     GenericSignature *invokeGenericSig;
+    GenericEnvironment *invokeGenericEnv;
     GenericParamList *invokeGenericParams;
     
     SILType blockType;
@@ -3628,7 +3658,7 @@
         parseValueName(invokeName) ||
         parseApplySubstitutions(parsedSubs) ||
         P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
-        parseSILType(invokeTy, invokeGenericSig, invokeGenericParams) ||
+        parseSILType(invokeTy, invokeGenericSig, invokeGenericEnv, invokeGenericParams) ||
         P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
         parseSILIdentifier(type, typeLoc,
                            diag::expected_tok_in_sil_instr, "type") ||
@@ -3654,8 +3684,9 @@
         return true;
       }
       if (getApplySubstitutionsFromParsed(*this,
-                                          invokeGenericSig,
                                           invokeGenericParams,
+                                          invokeGenericSig,
+                                          invokeGenericEnv,
                                           parsedSubs, subs))
         return true;
     }
@@ -3702,10 +3733,11 @@
   SILType Ty;
   SourceLoc TypeLoc;
   GenericSignature *GenericSig = nullptr;
+  GenericEnvironment *GenericEnv = nullptr;
   GenericParamList *GenericParams = nullptr;
   if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") ||
       P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
-      parseSILType(Ty, TypeLoc, GenericSig, GenericParams))
+      parseSILType(Ty, TypeLoc, GenericSig, GenericEnv, GenericParams))
     return true;
 
   auto FTI = Ty.getAs<SILFunctionType>();
@@ -3716,11 +3748,13 @@
 
   SmallVector<Substitution, 4> subs;
   if (!parsedSubs.empty()) {
-    if (!GenericParams) {
+    if (!GenericSig) {
       P.diagnose(TypeLoc, diag::sil_substitutions_on_non_polymorphic_type);
       return true;
     }
-    if (getApplySubstitutionsFromParsed(*this, GenericSig, GenericParams,
+    if (getApplySubstitutionsFromParsed(*this,
+                                        GenericParams,
+                                        GenericSig, GenericEnv,
                                         parsedSubs, subs))
       return true;
   }
@@ -3958,8 +3992,10 @@
     // the scope.
     Scope Body(this, ScopeKind::FunctionBody);
     GenericSignature *GenericSig;
-    GenericParamList *ContextParams;
-    if (FunctionState.parseSILType(FnType, GenericSig, ContextParams,
+    GenericEnvironment *GenericEnv;
+    GenericParamList *GenericParams;
+    if (FunctionState.parseSILType(FnType,
+                                   GenericSig, GenericEnv, GenericParams,
                                    true/*IsFuncDecl*/))
       return true;
     auto SILFnType = FnType.getAs<SILFunctionType>();
@@ -3989,17 +4025,15 @@
     if (consumeIf(tok::l_brace)) {
       isDefinition = true;
       
-      // FIXME: Get the generic parameters from the function type. We'll want
-      // to parse this from the TypeRepr when SILFunctionType loses its context
-      // params.
-      FunctionState.F->setContextGenericParams(ContextParams);
+      FunctionState.F->setGenericEnvironment(GenericEnv);
 
-      // Resolve specialization attributes after setting ContextParams.
+      // Resolve specialization attributes after setting GenericEnv.
       for (auto &Attr : SpecAttrs) {
         SmallVector<Substitution, 4> Subs;
         if (getApplySubstitutionsFromParsed(FunctionState,
+                                            GenericParams,
                                             GenericSig,
-                                            ContextParams,
+                                            GenericEnv,
                                             Attr.subs, Subs)) {
           return true;
         }
@@ -4341,6 +4375,7 @@
 ProtocolConformance *SILParser::parseProtocolConformance(
            ProtocolDecl *&proto,
            GenericSignature *&genericSig,
+           GenericEnvironment *&genericEnv,
            GenericParamList *&genericParams,
            bool localScope) {
   // Parse generic params for the protocol conformance. We need to make sure
@@ -4354,7 +4389,8 @@
 
   genericParams = P.maybeParseGenericParams().getPtrOrNull();
   if (genericParams) {
-    genericSig = handleSILGenericParams(P.Context, genericParams, &P.SF);
+    std::tie(genericSig, genericEnv) =
+        handleSILGenericParams(P.Context, genericParams, &P.SF);
   }
 
   ProtocolConformance *retVal = parseProtocolConformanceHelper(proto,
@@ -4402,15 +4438,19 @@
       return nullptr;
     ProtocolDecl *dummy;
     GenericSignature *sig;
+    GenericEnvironment *env;
     GenericParamList *gp;
-    auto genericConform = parseProtocolConformance(dummy, sig, gp, localScope);
+    auto genericConform = parseProtocolConformance(dummy, sig, env, gp,
+                                                   localScope);
     if (!genericConform)
       return nullptr;
     if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
       return nullptr;
 
     SmallVector<Substitution, 4> subs;
-    if (getApplySubstitutionsFromParsed(*this, sig, gp, parsedSubs, subs))
+    if (getApplySubstitutionsFromParsed(*this,
+                                        gp,
+                                        sig, env, parsedSubs, subs))
       return nullptr;
 
     auto result = P.Context.getSpecializedConformance(
@@ -4471,9 +4511,12 @@
   // Parse the protocol conformance.
   ProtocolDecl *proto;
   GenericSignature *dummySig;
+  GenericEnvironment *dummyEnv;
   GenericParamList *dummyParams;
   auto conf = WitnessState.parseProtocolConformance(proto,
-                                                    dummySig, dummyParams,
+                                                    dummySig,
+                                                    dummyEnv,
+                                                    dummyParams,
                                                     false/*localScope*/);
 
   NormalProtocolConformance *theConformance = conf ?
@@ -4906,12 +4949,13 @@
     // We need to turn on InSILBody to parse the function reference.
     Lexer::SILBodyRAII Tmp(*L);
     GenericSignature *IgnoredSig;
+    GenericEnvironment *IgnoredEnv;
     GenericParamList *IgnoredParams;
     Scope S(this, ScopeKind::TopLevel);
     Scope Body(this, ScopeKind::FunctionBody);
     if ((ScopeState.parseGlobalName(FnName)) ||
         parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
-        ScopeState.parseSILType(Ty, IgnoredSig, IgnoredParams, true))
+        ScopeState.parseSILType(Ty, IgnoredSig, IgnoredEnv, IgnoredParams, true))
       return true;
 
     // The function doesn't exist yet. Create a zombie forward declaration.
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index 533b470..9637a63 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -16,8 +16,8 @@
 #include "swift/SIL/SILInstruction.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/CFG.h"
-// FIXME: For mapTypeInContext
 #include "swift/AST/ArchetypeBuilder.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/GraphWriter.h"
@@ -41,7 +41,7 @@
 SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage,
                                  StringRef name,
                                  CanSILFunctionType loweredType,
-                                 GenericParamList *contextGenericParams,
+                                 GenericEnvironment *genericEnv,
                                  Optional<SILLocation> loc,
                                  IsBare_t isBareSILFunction,
                                  IsTransparent_t isTrans,
@@ -62,7 +62,7 @@
   }
 
   auto fn = new (M) SILFunction(M, linkage, name,
-                                loweredType, contextGenericParams, loc,
+                                loweredType, genericEnv, loc,
                                 isBareSILFunction, isTrans, isFragile, isThunk,
                                 classVisibility, inlineStrategy, E,
                                 insertBefore, debugScope, DC);
@@ -73,7 +73,7 @@
 
 SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
                          StringRef Name, CanSILFunctionType LoweredType,
-                         GenericParamList *contextGenericParams,
+                         GenericEnvironment *genericEnv,
                          Optional<SILLocation> Loc,
                          IsBare_t isBareSILFunction,
                          IsTransparent_t isTrans,
@@ -87,8 +87,7 @@
   : Module(Module),
     Name(Name),
     LoweredType(LoweredType),
-    // FIXME: Context params should be independent of the function type.
-    ContextGenericParams(contextGenericParams),
+    GenericEnv(genericEnv),
     DeclCtx(DC),
     DebugScope(DebugScope),
     Bare(isBareSILFunction),
@@ -188,7 +187,7 @@
 
 Type SILFunction::mapTypeIntoContext(Type type) const {
   return ArchetypeBuilder::mapTypeIntoContext(getModule().getSwiftModule(),
-                                              getContextGenericParams(),
+                                              getGenericEnvironment(),
                                               type);
 }
 
@@ -290,7 +289,7 @@
 
 Type SILFunction::mapTypeOutOfContext(Type type) const {
   return ArchetypeBuilder::mapTypeOutOfContext(getModule().getSwiftModule(),
-                                               getContextGenericParams(),
+                                               getGenericEnvironment(),
                                                type);
 }
 
@@ -558,12 +557,13 @@
   if (ForwardingSubs)
     return *ForwardingSubs;
 
-  auto *params = getContextGenericParams();
-  if (!params)
+  auto *env = getGenericEnvironment();
+  if (!env)
     return {};
 
   auto sig = getLoweredFunctionType()->getGenericSignature();
-  ForwardingSubs = params->getForwardingSubstitutions(sig);
+  auto *M = getModule().getSwiftModule();
+  ForwardingSubs = env->getForwardingSubstitutions(M, sig);
 
   return *ForwardingSubs;
 }
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 7754fd6..da2c1cc 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -1682,9 +1682,7 @@
   // First, get a function type for the constant.  This creates the
   // right type for a getter or setter.
   auto formalInterfaceType = makeConstantInterfaceType(constant);
-  GenericParamList *contextGenerics, *innerGenerics;
-  std::tie(contextGenerics, innerGenerics)
-    = getConstantContextGenericParams(constant);
+  auto *genericEnv = getConstantGenericEnvironment(constant);
 
   // The formal type is just that with the right representation.
   auto rep = getDeclRefRepresentation(constant);
@@ -1714,8 +1712,7 @@
     formalInterfaceType,
     loweredInterfaceType,
     silFnType,
-    contextGenerics,
-    innerGenerics,
+    genericEnv
   };
   ConstantTypes[constant] = result;
   return result;
@@ -2091,8 +2088,7 @@
   SILConstantInfo overrideInfo;
   overrideInfo.LoweredInterfaceType = overrideLoweredInterfaceTy;
   overrideInfo.SILFnType = fnTy;
-  overrideInfo.ContextGenericParams = derivedInfo.ContextGenericParams;
-  overrideInfo.InnerGenericParams = derivedInfo.InnerGenericParams;
+  overrideInfo.GenericEnv = derivedInfo.GenericEnv;
   ConstantOverrideTypes[{derived, base}] = overrideInfo;
 
   return overrideInfo;
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index 8c2ef8d..dc73acb 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -409,13 +409,13 @@
 
 SILFunction *SILModule::createFunction(
     SILLinkage linkage, StringRef name, CanSILFunctionType loweredType,
-    GenericParamList *contextGenericParams, Optional<SILLocation> loc,
+    GenericEnvironment *genericEnv, Optional<SILLocation> loc,
     IsBare_t isBareSILFunction, IsTransparent_t isTrans, IsFragile_t isFragile,
     IsThunk_t isThunk, SILFunction::ClassVisibility_t classVisibility,
     Inline_t inlineStrategy, EffectsKind EK, SILFunction *InsertBefore,
     const SILDebugScope *DebugScope, DeclContext *DC) {
   return SILFunction::create(*this, linkage, name, loweredType,
-                             contextGenericParams, loc, isBareSILFunction,
+                             genericEnv, loc, isBareSILFunction,
                              isTrans, isFragile, isThunk, classVisibility,
                              inlineStrategy, EK, InsertBefore, DebugScope, DC);
 }
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index ad3bb3e..4baac97 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1794,33 +1794,35 @@
   llvm::DenseMap<CanType, Identifier> Aliases;
   llvm::DenseSet<Identifier> UsedNames;
   
-  auto params = ContextGenericParams;
-  llvm::SmallString<16> disambiguatedNameBuf;
-  unsigned disambiguatedNameCounter = 1;
-  while (params) {
-    for (GenericTypeParamDecl *param : params->getParams()) {
-      Identifier name = param->getName();
+  auto sig = getLoweredFunctionType()->getGenericSignature();
+  auto *env = getGenericEnvironment();
+  if (sig && env) {
+    llvm::SmallString<16> disambiguatedNameBuf;
+    unsigned disambiguatedNameCounter = 1;
+    for (auto *paramTy : sig->getGenericParams()) {
+      auto *archetypeTy = mapTypeIntoContext(paramTy)->getAs<ArchetypeType>();
+      assert(archetypeTy);
+
+      Identifier name = archetypeTy->getName();
       while (!UsedNames.insert(name).second) {
         disambiguatedNameBuf.clear();
         {
           llvm::raw_svector_ostream names(disambiguatedNameBuf);
-          names << param->getName() << disambiguatedNameCounter++;
+          names << archetypeTy->getName() << disambiguatedNameCounter++;
         }
         name = getASTContext().getIdentifier(disambiguatedNameBuf);
       }
-      if (name != param->getName())
-        Aliases[CanType(param->getArchetype())] = name;
+      if (name != archetypeTy->getName())
+        Aliases[CanType(archetypeTy)] = name;
     }
-    
-    params = params->getOuterParameters();
   }
 
   {
-    PrintOptions withContextGenericParams = PrintOptions::printSIL();
-    withContextGenericParams.ContextGenericParams = ContextGenericParams;
-    withContextGenericParams.AlternativeTypeNames =
+    PrintOptions withGenericEnvironment = PrintOptions::printSIL();
+    withGenericEnvironment.GenericEnv = env;
+    withGenericEnvironment.AlternativeTypeNames =
       Aliases.empty() ? nullptr : &Aliases;
-    LoweredType->print(OS, withContextGenericParams);
+    LoweredType->print(OS, withGenericEnvironment);
   }
   
   if (!isExternalDeclaration()) {
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 9b9e892..beb3fa4 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -22,6 +22,7 @@
 #include "swift/AST/AnyFunctionRef.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/Decl.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/Types.h"
 #include "swift/SIL/PrettyStackTrace.h"
@@ -59,15 +60,10 @@
   A = A->getPrimary();
 
   // Ok, we have a primary archetype, make sure it is in the nested generic
-  // parameters of our caller.
-  for (auto *params = F->getContextGenericParams();
-       params != nullptr;
-       params = params->getOuterParameters()) {
-
-    for (auto param : params->getParams())
-      if (param->getArchetype()->isEqual(A))
-        return true;
-  }
+  // environment of our caller.
+  if (auto *genericEnv = F->getGenericEnvironment())
+    if (genericEnv->getArchetypeToInterfaceMap().count(A))
+      return true;
 
   return false;
 }
@@ -1757,9 +1753,9 @@
     auto methodTy = constantInfo.SILFnType;
 
     // Map interface types to archetypes.
-    if (auto *params = constantInfo.ContextGenericParams) {
+    if (auto *env = constantInfo.GenericEnv) {
       auto sig = constantInfo.SILFnType->getGenericSignature();
-      auto subs = params->getForwardingSubstitutions(sig);
+      auto subs = env->getForwardingSubstitutions(M, sig);
       methodTy = methodTy->substGenericArgs(F.getModule(), M, subs);
     }
     assert(!methodTy->isPolymorphic());
@@ -3308,13 +3304,13 @@
 
     // Make sure that our SILFunction only has context generic params if our
     // SILFunctionType is non-polymorphic.
-    if (F->getContextGenericParams()) {
+    if (F->getGenericEnvironment()) {
       require(FTy->isPolymorphic(),
-              "non-generic function definitions cannot have context "
-              "archetypes");
+              "non-generic function definitions cannot have a "
+              "generic environment");
     } else {
       require(!FTy->isPolymorphic(),
-              "generic function definition must have context archetypes");
+              "generic function definition must have a generic environment");
     }
 
     // Otherwise, verify the body of the function.
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index e4d4c6c..14aca5f 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -1658,7 +1658,7 @@
     sig = genTy->getGenericSignature()->getCanonicalSignature();
     resultTy = ArchetypeBuilder::mapTypeOutOfContext(
         TC.M.getSwiftModule(),
-        funcInfo.ContextGenericParams,
+        funcInfo.GenericEnv,
         resultTy)->getCanonicalType();
   }
   
@@ -1748,16 +1748,16 @@
   return CanFunctionType::get(classType, resultType, extInfo);
 }
 
-GenericParamList *
-TypeConverter::getEffectiveGenericParams(AnyFunctionRef fn,
-                                         CaptureInfo captureInfo) {
+GenericEnvironment *
+TypeConverter::getEffectiveGenericEnvironment(AnyFunctionRef fn,
+                                              CaptureInfo captureInfo) {
   auto dc = fn.getAsDeclContext();
 
   if (dc->getParent()->isLocalContext() &&
       !captureInfo.hasGenericParamCaptures())
     return nullptr;
 
-  return dc->getGenericParamsOfContext();
+  return dc->getGenericEnvironmentOfContext();
 }
 
 CanGenericSignature
@@ -1904,9 +1904,9 @@
   }
 }
 
-/// Get the context generic parameters for an entity.
-std::pair<GenericParamList *, GenericParamList *>
-TypeConverter::getConstantContextGenericParams(SILDeclRef c) {
+/// Get the generic environment for an entity.
+GenericEnvironment *
+TypeConverter::getConstantGenericEnvironment(SILDeclRef c) {
   ValueDecl *vd = c.loc.dyn_cast<ValueDecl *>();
   
   /// Get the function generic params, including outer params.
@@ -1915,48 +1915,37 @@
     if (auto *ACE = c.getAbstractClosureExpr()) {
       auto captureInfo = getLoweredLocalCaptures(ACE);
 
-      // Closures are currently never natively generic.
-      return {getEffectiveGenericParams(ACE, captureInfo), nullptr};
+      return getEffectiveGenericEnvironment(ACE, captureInfo);
     }
     FuncDecl *func = cast<FuncDecl>(vd);
     auto captureInfo = getLoweredLocalCaptures(func);
 
-    return {getEffectiveGenericParams(func, captureInfo),
-            func->getGenericParams()};
+    return getEffectiveGenericEnvironment(func, captureInfo);
   }
   case SILDeclRef::Kind::EnumElement: {
     auto eltDecl = cast<EnumElementDecl>(vd);
-    return {
-      eltDecl->getDeclContext()->getGenericParamsOfContext(),
-      nullptr
-    };
+    return eltDecl->getDeclContext()->getGenericEnvironmentOfContext();
   }
   case SILDeclRef::Kind::Allocator:
   case SILDeclRef::Kind::Initializer:
   case SILDeclRef::Kind::Destroyer:
   case SILDeclRef::Kind::Deallocator: {
     auto *afd = cast<AbstractFunctionDecl>(vd);
-    return {afd->getGenericParamsOfContext(), afd->getGenericParams()};
+    return afd->getGenericEnvironmentOfContext();
   }
   case SILDeclRef::Kind::GlobalAccessor:
   case SILDeclRef::Kind::GlobalGetter: {
-    return {
-      cast<VarDecl>(vd)->getDeclContext()->getGenericParamsOfContext(),
-      nullptr,
-    };
+    return vd->getDeclContext()->getGenericEnvironmentOfContext();
   }
   case SILDeclRef::Kind::IVarInitializer:
   case SILDeclRef::Kind::IVarDestroyer:
-    return {cast<ClassDecl>(vd)->getGenericParamsOfContext(), nullptr};
+    return cast<ClassDecl>(vd)->getGenericEnvironmentOfContext();
   case SILDeclRef::Kind::DefaultArgGenerator:
-    // Use the context generic parameters of the original declaration.
-    return getConstantContextGenericParams(SILDeclRef(c.getDecl()));
+    // Use the generic environment of the original function.
+    return getConstantGenericEnvironment(SILDeclRef(c.getDecl()));
   case SILDeclRef::Kind::StoredPropertyInitializer:
-    // Use the context generic parameters of the containing type.
-    return {
-      c.getDecl()->getDeclContext()->getGenericParamsOfContext(),
-      nullptr,
-    };
+    // Use the generic environment of the containing type.
+    return c.getDecl()->getDeclContext()->getGenericEnvironmentOfContext();
   }
 }
 
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 43d637f..e8682ec 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -575,8 +575,7 @@
 
   assert(F->empty() && "already emitted function?!");
 
-  F->setContextGenericParams(
-                         Types.getConstantInfo(constant).ContextGenericParams);
+  F->setGenericEnvironment(Types.getConstantInfo(constant).GenericEnv);
 
   // Create a debug scope for the function using astNode as source location.
   F->setDebugScope(new (M) SILDebugScope(Loc, F));
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index e019161..ba393c7 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -185,7 +185,7 @@
   /// Get or create the declaration of a reabstraction thunk with the
   /// given signature.
   SILFunction *getOrCreateReabstractionThunk(
-                                           GenericParamList *thunkContextParams,
+                                           GenericEnvironment *genericEnv,
                                            CanSILFunctionType thunkType,
                                            CanSILFunctionType fromType,
                                            CanSILFunctionType toType,
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index ce9c2bf..5e247c3 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -321,14 +321,10 @@
   // Build the invoke function signature. The block will capture the original
   // function value.
   auto fnTy = fn.getType().castTo<SILFunctionType>();
-  auto fnInterfaceTy = cast<SILFunctionType>(CanType(
-    ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(),
-                                          F.getContextGenericParams(),
-                                          fnTy)));
-  auto blockInterfaceTy = cast<SILFunctionType>(CanType(
-    ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(),
-                                          F.getContextGenericParams(),
-                                          blockTy)));
+  auto fnInterfaceTy = cast<SILFunctionType>(
+    F.mapTypeOutOfContext(fnTy)->getCanonicalType());
+  auto blockInterfaceTy = cast<SILFunctionType>(
+    F.mapTypeOutOfContext(blockTy)->getCanonicalType());
 
   auto storageTy = SILBlockStorageType::get(fnTy);
   auto storageInterfaceTy = SILBlockStorageType::get(fnInterfaceTy);
@@ -363,7 +359,7 @@
 
   // Create the invoke function. Borrow the mangling scheme from reabstraction
   // thunks, which is what we are in spirit.
-  auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(),
+  auto thunk = SGM.getOrCreateReabstractionThunk(F.getGenericEnvironment(),
                                                  invokeTy,
                                                  fnTy,
                                                  blockTy,
@@ -371,7 +367,7 @@
 
   // Build it if necessary.
   if (thunk->empty()) {
-    thunk->setContextGenericParams(F.getContextGenericParams());
+    thunk->setGenericEnvironment(F.getGenericEnvironment());
     SILGenFunction thunkSGF(SGM, *thunk);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildFuncToBlockInvokeBody(thunkSGF, loc, blockTy, storageTy, fnTy);
@@ -612,7 +608,7 @@
   // Declare the thunk.
   auto blockTy = block.getType().castTo<SILFunctionType>();
   auto thunkTy = buildThunkType(block, funcTy, substFnTy, subs);
-  auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(),
+  auto thunk = SGM.getOrCreateReabstractionThunk(F.getGenericEnvironment(),
                                                  thunkTy,
                                                  blockTy,
                                                  funcTy,
@@ -621,7 +617,7 @@
   // Build it if necessary.
   if (thunk->empty()) {
     SILGenFunction thunkSGF(SGM, *thunk);
-    thunk->setContextGenericParams(F.getContextGenericParams());
+    thunk->setGenericEnvironment(F.getGenericEnvironment());
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildBlockToFuncThunkBody(thunkSGF, loc, blockTy, funcTy);
   }
@@ -852,7 +848,7 @@
   auto swiftFnTy = swiftInfo.SILFnType->substGenericArgs(gen.SGM.M, mod, subs);
 
   // We must have the same context archetypes as the unthunked function.
-  assert(objcInfo.ContextGenericParams == swiftInfo.ContextGenericParams);
+  assert(objcInfo.GenericEnv == swiftInfo.GenericEnv);
 
   SmallVector<ManagedValue, 8> bridgedArgs;
   bridgedArgs.reserve(objcFnTy->getParameters().size());
@@ -959,8 +955,8 @@
     SGM.M, SGM.M.getSwiftModule(), subs);
   SILType substSILTy = SILType::getPrimitiveObjectType(substTy);
   
-  // Use the same context generic params as the native entry point.
-  F.setContextGenericParams(nativeInfo.ContextGenericParams);
+  // Use the same generic environment as the native entry point.
+  F.setGenericEnvironment(nativeInfo.GenericEnv);
 
   auto loc = thunk.getAsRegularLocation();
   loc.markAutoGenerated();
@@ -1121,8 +1117,8 @@
   auto nativeFnTy = F.getLoweredFunctionType();
   assert(nativeFnTy == nativeCI.SILFnType);
 
-  // Use the same context generic params as the native entry point.
-  F.setContextGenericParams(nativeCI.ContextGenericParams);
+  // Use the same generic environment as the native entry point.
+  F.setGenericEnvironment(nativeCI.GenericEnv);
   
   // Find the foreign error convention and 'self' parameter index.
   Optional<ForeignErrorConvention> foreignError;
@@ -1282,8 +1278,9 @@
     auto fnType = fn->getType().castTo<SILFunctionType>();
     fnType = fnType->substGenericArgs(SGM.M, SGM.SwiftModule, subs);
 
-    CanType substResultTy{
-        ArchetypeBuilder::mapTypeIntoContext(fd, nativeFormalResultTy)};
+    auto substResultTy =
+        ArchetypeBuilder::mapTypeIntoContext(fd, nativeFormalResultTy)
+            ->getCanonicalType();
 
     auto resultMV = emitApply(fd, ManagedValue::forUnmanaged(fn),
                        subs, args, fnType,
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 55559e4..9abe4e3 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -17,6 +17,7 @@
 #include "RValue.h"
 #include "Scope.h"
 #include "swift/AST/AST.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Mangle.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/SILUndef.h"
@@ -491,9 +492,10 @@
   ArrayRef<Substitution> subs;
   // Call the initializer.
   ArrayRef<Substitution> forwardingSubs;
-  if (auto *genericParamList = ctor->getGenericParamsOfContext()) {
+  if (auto *genericEnv = ctor->getGenericEnvironmentOfContext()) {
     auto *genericSig = ctor->getGenericSignatureOfContext();
-    forwardingSubs = genericParamList->getForwardingSubstitutions(genericSig);
+    forwardingSubs = genericEnv->getForwardingSubstitutions(
+        SGM.SwiftModule, genericSig);
   }
   std::tie(initVal, initTy, subs)
     = emitSiblingMethodRef(Loc, selfValue, initConstant, forwardingSubs);
@@ -871,10 +873,11 @@
 
         // Get the substitutions for the constructor context.
         ArrayRef<Substitution> subs;
-        auto *genericParams = dc->getGenericParamsOfContext();
-        if (genericParams) {
+        auto *genericEnv = dc->getGenericEnvironmentOfContext();
+        if (genericEnv) {
           auto *genericSig = dc->getGenericSignatureOfContext();
-          subs = genericParams->getForwardingSubstitutions(genericSig);
+          subs = genericEnv->getForwardingSubstitutions(
+              SGM.SwiftModule, genericSig);
         }
 
         // Get the type of the initialization result, in terms
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 9c923e0..362846c 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -23,6 +23,7 @@
 #include "swift/SIL/SILWitnessVisitor.h"
 #include "swift/SIL/TypeLowering.h"
 #include "swift/AST/AST.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Mangle.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/NameLookup.h"
@@ -1768,34 +1769,36 @@
     nameBuffer = mangler.finalize();
   }
 
-  // Collect the context generic parameters for the witness.
-  //
-  // FIXME: SILFunction::ContextGenericParams needs to be a GenericSignature
-  // instead.
-  GenericParamList *witnessContextParams = nullptr;
+  // Collect the generic environment for the witness.
+  TypeSubstitutionMap witnessContextParams;
 
   // Concrete witness thunks use the context archetypes of the conformance.
   if (conformance) {
-    witnessContextParams = conformance->getGenericParams();
+    if (auto *genericEnv = conformance->getGenericEnvironment())
+      witnessContextParams = genericEnv->getInterfaceToArchetypeMap();
 
     // If the requirement is generic, reparent the requirement parameters to
     // the conformance parameters.
-    if (auto reqtParams = requirementInfo.InnerGenericParams) {
-      // Preserve the depth of generic arguments by adding an empty outer generic
-      // param list if the conformance is concrete.
-      if (!witnessContextParams)
-        witnessContextParams = GenericParamList::getEmpty(getASTContext());
+    for (auto pair : requirementInfo.GenericEnv->getInterfaceToArchetypeMap()) {
+      // Skip the 'Self' parameter.
+      if (auto *archetypeTy = pair.second->getAs<ArchetypeType>())
+        if (archetypeTy->getSelfProtocol() != nullptr)
+          continue;
 
-      witnessContextParams
-        = reqtParams->cloneWithOuterParameters(getASTContext(),
-                                               witnessContextParams);
+      auto result = witnessContextParams.insert(pair);
+      assert(result.second);
     }
 
   // Default witness thunks use the context archetypes of the requirement.
   } else {
-    witnessContextParams = requirementInfo.ContextGenericParams;
+    witnessContextParams = requirementInfo.GenericEnv
+        ->getInterfaceToArchetypeMap();
   }
 
+  GenericEnvironment *witnessEnv = nullptr;
+  if (!witnessContextParams.empty())
+    witnessEnv = GenericEnvironment::get(getASTContext(), witnessContextParams);
+
   // If the thunked-to function is set to be always inlined, do the
   // same with the witness, on the theory that the user wants all
   // calls removed if possible, e.g. when we're able to devirtualize
@@ -1814,7 +1817,7 @@
 
   auto *f = M.createFunction(
       linkage, nameBuffer, witnessSILFnType,
-      witnessContextParams, SILLocation(witness.getDecl()),
+      witnessEnv, SILLocation(witness.getDecl()),
       IsNotBare, IsTransparent, isFragile, IsThunk,
       SILFunction::NotRelevant, InlineStrategy);
 
@@ -1959,7 +1962,7 @@
 }
 
 SILFunction *SILGenModule::
-getOrCreateReabstractionThunk(GenericParamList *thunkContextParams,
+getOrCreateReabstractionThunk(GenericEnvironment *genericEnv,
                               CanSILFunctionType thunkType,
                               CanSILFunctionType fromType,
                               CanSILFunctionType toType,
@@ -1981,11 +1984,11 @@
     // Substitute context parameters out of the "from" and "to" types.
     auto fromInterfaceType
         = ArchetypeBuilder::mapTypeOutOfContext(
-            M.getSwiftModule(), thunkContextParams, fromType)
+            M.getSwiftModule(), genericEnv, fromType)
                 ->getCanonicalType();
     auto toInterfaceType
         = ArchetypeBuilder::mapTypeOutOfContext(
-            M.getSwiftModule(), thunkContextParams, toType)
+            M.getSwiftModule(), genericEnv, toType)
                 ->getCanonicalType();
 
     mangler.mangleType(fromInterfaceType, /*uncurry*/ 0);
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 6a6a111..4bc9057 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -20,6 +20,7 @@
 #include "Scope.h"
 #include "swift/Basic/Fallthrough.h"
 #include "swift/AST/AST.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/SILUndef.h"
 
@@ -816,9 +817,9 @@
   // Forward substitutions.
   ArrayRef<Substitution> subs;
   auto constantInfo = getConstantInfo(to);
-  if (auto gp = constantInfo.ContextGenericParams) {
+  if (auto *env = constantInfo.GenericEnv) {
     auto sig = constantInfo.SILFnType->getGenericSignature();
-    subs = gp->getForwardingSubstitutions(sig);
+    subs = env->getForwardingSubstitutions(SGM.SwiftModule, sig);
   }
 
   SILValue toFn = getNextUncurryLevelRef(*this, vd, to, from.isDirectReference,
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 16685d8..15d9d72 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -22,9 +22,8 @@
 #include "Initialization.h"
 #include "swift/AST/AST.h"
 #include "swift/AST/DiagnosticsSIL.h"
-#include "swift/AST/Decl.h"
-#include "swift/AST/Types.h"
 #include "swift/AST/DiagnosticsCommon.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Mangle.h"
 #include "swift/SIL/PrettyStackTrace.h"
 #include "swift/SIL/SILArgument.h"
@@ -1585,9 +1584,10 @@
 getNonMemberVarDeclSubstitutions(SILGenModule &SGM, VarDecl *var) {
   ArrayRef<Substitution> substitutions;
   auto *dc = var->getDeclContext();
-  if (auto genericParams = dc->getGenericParamsOfContext()) {
+  if (auto *genericEnv = dc->getGenericEnvironmentOfContext()) {
     auto *genericSig = dc->getGenericSignatureOfContext();
-    substitutions = genericParams->getForwardingSubstitutions(genericSig);
+    substitutions = genericEnv->getForwardingSubstitutions(
+        SGM.SwiftModule, genericSig);
   }
   return substitutions;
 }
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index cf0063f..c1acbd1 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -98,7 +98,7 @@
   ArrayRef<Substitution> WitnessSubs;
 
   CanGenericSignature GenericSig;
-  GenericParamList *GenericParams;
+  GenericEnvironment *GenericEnv;
 
   // Assume that we don't need to reabstract 'self'.  Right now,
   // that's always true; if we ever reabstract Optional (or other
@@ -128,7 +128,7 @@
       WitnessStorage(witness->getAccessorStorageDecl()),
       WitnessStoragePattern(AbstractionPattern::getInvalid()),
       WitnessSubs(subs),
-      GenericParams(nullptr),
+      GenericEnv(nullptr),
       SelfInterfaceType(selfInterfaceType->getCanonicalType()),
       SubstSelfType(selfType->getCanonicalType()),
       TheAccessSemantics(AccessSemantics::Ordinary),
@@ -178,11 +178,11 @@
     if (conformance) {
       if (auto signature = conformance->getGenericSignature())
         emitter.GenericSig = signature->getCanonicalSignature();
-      emitter.GenericParams = conformance->getGenericParams();
+      emitter.GenericEnv = conformance->getGenericEnvironment();
     } else {
       auto signature = requirement->getGenericSignatureOfContext();
       emitter.GenericSig = signature->getCanonicalSignature();
-      emitter.GenericParams = requirement->getGenericParamsOfContext();
+      emitter.GenericEnv = requirement->getGenericEnvironmentOfContext();
     }
 
     emitter.RequirementStorage = requirement->getAccessorStorageDecl();
@@ -218,7 +218,7 @@
 
     if (auto signature = witness->getGenericSignatureOfContext())
       emitter.GenericSig = signature->getCanonicalSignature();
-    emitter.GenericParams = constantInfo.ContextGenericParams;
+    emitter.GenericEnv = constantInfo.GenericEnv;
 
     emitter.RequirementStorage = emitter.WitnessStorage;
     emitter.RequirementStoragePattern = emitter.WitnessStoragePattern;
@@ -552,7 +552,7 @@
                                 F.isTransparent(),
                                 F.isFragile());
 
-  callback->setContextGenericParams(GenericParams);
+  callback->setGenericEnvironment(GenericEnv);
   callback->setDebugScope(new (SGM.M) SILDebugScope(Witness, callback));
 
   PrettyStackTraceSILFunction X("silgen materializeForSet callback", callback);
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 21b8c4d..8f47b27 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2450,7 +2450,7 @@
   auto thunkType = gen.buildThunkType(fn, expectedType,
                                   substFnType, substitutions);
   auto thunk = gen.SGM.getOrCreateReabstractionThunk(
-                                       gen.F.getContextGenericParams(),
+                                       gen.F.getGenericEnvironment(),
                                        thunkType,
                                        fn.getType().castTo<SILFunctionType>(),
                                        expectedType,
@@ -2459,7 +2459,7 @@
   // Build it if necessary.
   if (thunk->empty()) {
     // Borrow the context archetypes from the enclosing function.
-    thunk->setContextGenericParams(gen.F.getContextGenericParams());
+    thunk->setGenericEnvironment(gen.F.getGenericEnvironment());
     SILGenFunction thunkSGF(gen.SGM, *thunk);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildThunkBody(thunkSGF, loc,
@@ -2679,8 +2679,8 @@
   auto fTy = implFn->getLoweredFunctionType();
   
   ArrayRef<Substitution> subs;
-  if (auto context = fd->getGenericParamsOfContext()) {
-    F.setContextGenericParams(context);
+  if (auto *genericEnv = fd->getGenericEnvironment()) {
+    F.setGenericEnvironment(genericEnv);
     subs = getForwardingSubstitutions();
     fTy = fTy->substGenericArgs(SGM.M, SGM.SwiftModule, subs);
 
@@ -2824,7 +2824,7 @@
 
 static void addConformanceToSubstitutionMap(SILGenModule &SGM,
                                 TypeSubstitutionMap &subs,
-                                GenericParamList *context,
+                                GenericEnvironment *genericEnv,
                                 CanType base,
                                 const ProtocolConformance *conformance) {
   conformance->forEachTypeWitness(nullptr, [&](AssociatedTypeDecl *assocTy,
@@ -2834,14 +2834,14 @@
       CanDependentMemberType::get(base, assocTy, SGM.getASTContext());
     auto replacement = sub.getReplacement()->getCanonicalType();
     replacement = ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(),
-                                                        context,
+                                                        genericEnv,
                                                         replacement)
       ->getCanonicalType();
     subs.insert({depTy.getPointer(), replacement});
     for (auto conformance : sub.getConformances()) {
       if (conformance.isAbstract())
         continue;
-      addConformanceToSubstitutionMap(SGM, subs, context,
+      addConformanceToSubstitutionMap(SGM, subs, genericEnv,
                                       depTy, conformance.getConcrete());
     }
     return false;
@@ -2860,7 +2860,8 @@
   TypeSubstitutionMap subs;
   subs.insert({selfParamTy.getPointer(), conformance->getInterfaceType()
                                                     ->getCanonicalType()});
-  addConformanceToSubstitutionMap(*this, subs, conformance->getGenericParams(),
+  addConformanceToSubstitutionMap(*this, subs,
+                                  conformance->getGenericEnvironment(),
                                   selfParamTy, conformance);
   
   // Drop requirements rooted in the applied generic parameters.
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index e2532ae..443f14a 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -93,7 +93,7 @@
   auto thunk =
       M.createFunction(SILLinkage::Private,
                        name, overrideInfo.SILFnType,
-                       derivedDecl->getGenericParams(), loc, IsBare,
+                       derivedDecl->getGenericEnvironment(), loc, IsBare,
                        IsNotTransparent, IsNotFragile);
   thunk->setDebugScope(new (M) SILDebugScope(loc, thunk));
 
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index e1c0e3f..748f8b8 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -46,6 +46,7 @@
 #include "swift/SIL/SILCloner.h"
 #include "swift/SIL/TypeSubstCloner.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/Statistic.h"
@@ -444,7 +445,7 @@
   assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
 
   auto *Fn = M.createFunction(
-      Orig->getLinkage(), ClonedName, SubstTy, Orig->getContextGenericParams(),
+      Orig->getLinkage(), ClonedName, SubstTy, Orig->getGenericEnvironment(),
       Orig->getLocation(), Orig->isBare(), IsNotTransparent, Fragile,
       Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(),
       Orig->getEffectsKind(), Orig, Orig->getDebugScope());
@@ -866,7 +867,7 @@
 
   ArrayRef<Substitution> ApplySubs = PAI->getSubstitutions();
   auto genericSig = F->getLoweredFunctionType()->getGenericSignature();
-  auto *genericParams = F->getContextGenericParams();
+  auto *genericParams = F->getGenericEnvironment();
 
   if (!ApplySubs.empty()) {
     InterfaceSubs = genericSig->getSubstitutionMap(ApplySubs);
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 85297ce..bac3080 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -548,7 +548,7 @@
       // original function was de-serialized) and would not be code-gen'd.
       getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()),
       ClonedName, ClonedTy,
-      ClosureUser->getContextGenericParams(), ClosureUser->getLocation(),
+      ClosureUser->getGenericEnvironment(), ClosureUser->getLocation(),
       IsBare, ClosureUser->isTransparent(), CallSiteDesc.isFragile(),
       ClosureUser->isThunk(), ClosureUser->getClassVisibility(),
       ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
index 8ac5794..8dd4032 100644
--- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
+++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
@@ -14,6 +14,7 @@
 #include "swift/SILOptimizer/PassManager/Passes.h"
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/AST/DiagnosticsSIL.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/SILOptimizer/Utils/Devirtualize.h"
 #include "swift/SILOptimizer/Utils/Local.h"
 #include "swift/SILOptimizer/Utils/SILInliner.h"
@@ -435,7 +436,7 @@
         ApplySubs.insert(ApplySubs.end(), PAISubs.begin(), PAISubs.end());
       }
 
-      if (auto *params = CalleeFunction->getContextGenericParams()) {
+      if (auto *params = CalleeFunction->getGenericEnvironment()) {
         auto sig = CalleeFunction->getLoweredFunctionType()
             ->getGenericSignature();
         params->getSubstitutionMap(F->getModule().getSwiftModule(),
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index 3b43005..20daafe 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -566,7 +566,7 @@
          && "SILFunction missing DebugScope");
   assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
   auto *Fn = M.createFunction(
-      SILLinkage::Shared, ClonedName, ClonedTy, Orig->getContextGenericParams(),
+      SILLinkage::Shared, ClonedName, ClonedTy, Orig->getGenericEnvironment(),
       Orig->getLocation(), Orig->isBare(), IsNotTransparent, Fragile,
       Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(),
       Orig->getEffectsKind(), Orig, Orig->getDebugScope());
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index 737dbf2..9c54a3e 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -16,6 +16,7 @@
 #include "swift/SILOptimizer/Utils/Generics.h"
 #include "swift/SILOptimizer/Utils/GenericCloner.h"
 #include "swift/SIL/DebugUtils.h"
+#include "swift/AST/GenericEnvironment.h"
 
 using namespace swift;
 
@@ -187,13 +188,13 @@
 
   assert(GenericFunc->isDefinition() && "Expected definition to specialize!");
 
-  if (auto *params = GenericFunc->getContextGenericParams()) {
+  if (auto *env = GenericFunc->getGenericEnvironment()) {
     auto sig = GenericFunc->getLoweredFunctionType()->getGenericSignature();
 
     ArchetypeConformanceMap conformanceMap;
-    params->getSubstitutionMap(M.getSwiftModule(), sig,
-                               ParamSubs, ContextSubs,
-                               conformanceMap);
+    env->getSubstitutionMap(M.getSwiftModule(), sig,
+                            ParamSubs, ContextSubs,
+                            conformanceMap);
   }
 
   Mangle::Mangler Mangler;
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 08b0253..f21defe 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -21,6 +21,7 @@
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/Availability.h"
 #include "swift/AST/Expr.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/Basic/Defer.h"
 #include "llvm/ADT/SmallString.h"
@@ -1134,6 +1135,17 @@
   return Get;
 }
 
+static ArrayRef<Substitution>
+getForwardingSubstitutions(DeclContext *DC) {
+  if (auto *env = DC->getGenericEnvironmentOfContext()) {
+    auto *sig = DC->getGenericSignatureOfContext();
+    return env->getForwardingSubstitutions(
+        DC->getParentModule(), sig);
+  }
+
+  return { };
+}
+
 void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD,
                                VarDecl *BehaviorStorage,
                                FuncDecl *DefaultInitStorage,
@@ -1270,12 +1282,7 @@
   addTrivialAccessorsToStorage(Storage, *this);
   
   // Add the witnesses to the conformance.
-  ArrayRef<Substitution> MemberSubs;
-  if (auto *sig = DC->getGenericSignatureOfContext()) {
-    MemberSubs = DC->getGenericParamsOfContext()
-                   ->getForwardingSubstitutions(sig);
-  }
-  
+  auto MemberSubs = getForwardingSubstitutions(DC);
   BehaviorConformance->setWitness(BehaviorStorage,
                                  ConcreteDeclRef(Context, Storage, MemberSubs));
   BehaviorConformance->setWitness(BehaviorStorage->getGetter(),
@@ -1303,6 +1310,7 @@
     ->getResult();
 
   GenericSignature *genericSig = nullptr;
+  GenericEnvironment *genericEnv = nullptr;
 
   TypeSubstitutionMap interfaceMap = sig->getSubstitutionMap(SelfInterfaceSubs);
   auto SubstInterfaceTy = ParameterTy.subst(VD->getModuleContext(),
@@ -1321,6 +1329,7 @@
   if (DC->isTypeContext()) {
     if (DC->isGenericContext()) {
       genericSig = DC->getGenericSignatureOfContext();
+      genericEnv = DC->getGenericEnvironmentOfContext();
       SubstInterfaceTy = GenericFunctionType::get(genericSig,
                                                   DC->getSelfInterfaceType(),
                                                   SubstInterfaceTy,
@@ -1398,6 +1407,7 @@
 
   Parameter->setInterfaceType(SubstInterfaceTy);
   Parameter->setGenericSignature(genericSig);
+  Parameter->setGenericEnvironment(genericEnv);
 
   // Mark the method to be final, implicit, and private.  In a class, this
   // prevents it from being dynamically dispatched.
@@ -1439,12 +1449,7 @@
   addMemberToContextIfNeeded(Parameter, DC);
 
   // Add the witnesses to the conformance.
-  ArrayRef<Substitution> MemberSubs;
-  if (auto *sig = DC->getGenericSignatureOfContext()) {
-    MemberSubs = DC->getGenericParamsOfContext()
-    ->getForwardingSubstitutions(sig);
-  }
-
+  auto MemberSubs = getForwardingSubstitutions(DC);
   BehaviorConformance->setWitness(BehaviorParameter,
                                ConcreteDeclRef(Context, Parameter, MemberSubs));
 }
@@ -2132,6 +2137,7 @@
 
   // Set the interface type of the initializer.
   ctor->setGenericSignature(classDecl->getGenericSignatureOfContext());
+  ctor->setGenericEnvironment(classDecl->getGenericEnvironmentOfContext());
   tc.configureInterfaceType(ctor);
 
   // Set the contextual type of the initializer. This will go away one day.
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 4ee22b1..207b839 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -258,6 +258,7 @@
   Type selfIfaceTy = eqDecl->computeInterfaceSelfType(false);
   if (auto genericSig = parentDC->getGenericSignatureOfContext()) {
     eqDecl->setGenericSignature(genericSig);
+    eqDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
 
     Type enumIfaceTy = parentDC->getDeclaredInterfaceType();
     TupleTypeElt ifaceParamElts[] = {
@@ -411,6 +412,7 @@
   Type selfIfaceType = getterDecl->computeInterfaceSelfType(false);
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     getterDecl->setGenericSignature(sig);
+    getterDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
     interfaceType = GenericFunctionType::get(sig, selfIfaceType, methodType,
                                              AnyFunctionType::ExtInfo());
   } else
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 2a87972..d1dd805 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -320,6 +320,7 @@
   Type initIfaceType;
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     initDecl->setGenericSignature(sig);
+    initDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext());
 
     allocIfaceType = GenericFunctionType::get(sig, selfInterfaceType,
                                               interfaceType,
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index eaccf5a..7f939bf 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -148,6 +148,8 @@
   Type selfInterfaceType = getterDecl->computeInterfaceSelfType(false);
   if (auto sig = parentDC->getGenericSignatureOfContext()) {
     getterDecl->setGenericSignature(sig);
+    getterDecl->setGenericEnvironment(
+        parentDC->getGenericEnvironmentOfContext());
     interfaceType = GenericFunctionType::get(sig, selfInterfaceType,
                                              interfaceType,
                                              FunctionType::ExtInfo());
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 999b1b4..6ab832a 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -377,7 +377,17 @@
       continue;
 
     // Retrieve the interface type for this inherited type.
-    if (inheritedTy->hasArchetype())
+    //
+    // If we have a generic parameter, mapTypeOutOfContext() might not
+    // work yet, if we're calling this while building the generic
+    // signature. However, we're also not storing inheritedTy back
+    // anywhere, so it's OK to leave it as an archetype.
+    //
+    // FIXME: Ideally, we wouldn't have code paths that take a mix
+    // of archetypes and interface types. Other than generic parameters,
+    // the only time we get an interface type here is with invalid
+    // circular cases. That should be diagnosed elsewhere.
+    if (inheritedTy->hasArchetype() && !isa<GenericTypeParamDecl>(decl))
       inheritedTy = ArchetypeBuilder::mapTypeOutOfContext(DC, inheritedTy);
 
     // Check whether we inherited from the same type twice.
@@ -696,9 +706,10 @@
 }
 
 /// Expose TypeChecker's handling of GenericParamList to SIL parsing.
-GenericSignature *TypeChecker::handleSILGenericParams(
-                    GenericParamList *genericParams,
-                    DeclContext *DC) {
+std::pair<GenericSignature *, GenericEnvironment *>
+TypeChecker::handleSILGenericParams(GenericParamList *genericParams,
+                                    DeclContext *DC) {
+
   SmallVector<GenericParamList *, 2> nestedList;
   for (; genericParams; genericParams = genericParams->getOuterParameters()) {
     nestedList.push_back(genericParams);
@@ -712,23 +723,26 @@
   // Since the innermost GenericParamList is in the beginning of the vector,
   // we process in reverse order to handle the outermost list first.
   GenericSignature *parentSig = nullptr;
+  GenericEnvironment *parentEnv = nullptr;
+
   for (unsigned i = 0, e = nestedList.size(); i < e; i++) {
     auto genericParams = nestedList.rbegin()[i];
     bool invalid = false;
     auto *genericSig = validateGenericSignature(genericParams, DC, parentSig,
                                                 nullptr, invalid);
     if (invalid)
-      return nullptr;
+      return std::make_pair(nullptr, nullptr);
 
     revertGenericParamList(genericParams);
 
     ArchetypeBuilder builder(*DC->getParentModule(), Diags);
     checkGenericParamList(&builder, genericParams, parentSig);
-    finalizeGenericParamList(builder, genericParams, DC);
-
+    parentEnv = finalizeGenericParamList(builder, genericParams,
+                                         genericSig, DC);
     parentSig = genericSig;
   }
-  return parentSig;
+
+  return std::make_pair(parentSig, parentEnv);
 }
 
 /// Check whether the given type representation will be
@@ -2495,7 +2509,7 @@
     return;
   }
 
-  if (ED->getGenericParamsOfContext() != nullptr)
+  if (ED->getGenericEnvironmentOfContext() != nullptr)
     rawTy = ArchetypeBuilder::mapTypeIntoContext(ED, rawTy);
   if (rawTy->is<ErrorType>())
     return;
@@ -4698,7 +4712,8 @@
       gp->setOuterParameters(FD->getDeclContext()->getGenericParamsOfContext());
 
       if (TC.validateGenericFuncSignature(FD)) {
-        TC.markInvalidGenericSignature(FD);
+        auto *env = TC.markInvalidGenericSignature(FD);
+        FD->setGenericEnvironment(env);
       } else {
         // Create a fresh archetype builder.
         ArchetypeBuilder builder =
@@ -4721,14 +4736,18 @@
         TC.revertGenericFuncSignature(FD);
 
         // Assign archetypes.
-        TC.finalizeGenericParamList(builder, gp, FD);
+        auto *env = TC.finalizeGenericParamList(builder, gp, nullptr, FD);
+        FD->setGenericEnvironment(env);
       }
-    } else if (FD->getDeclContext()->isGenericContext()) {
+    } else if (FD->getDeclContext()->getGenericSignatureOfContext()) {
       if (TC.validateGenericFuncSignature(FD)) {
-        TC.markInvalidGenericSignature(FD);
+        auto *env = TC.markInvalidGenericSignature(FD);
+        FD->setGenericEnvironment(env);
       } else if (!FD->hasType()) {
         // Revert all of the types within the signature of the function.
         TC.revertGenericFuncSignature(FD);
+        FD->setGenericEnvironment(
+            FD->getDeclContext()->getGenericEnvironmentOfContext());
       } else {
         // Recursively satisfied.
         // FIXME: This is an awful hack.
@@ -4741,7 +4760,7 @@
     if (semaFuncDecl(FD, &resolver))
       return;
 
-    if (!FD->isGenericContext())
+    if (!FD->getGenericSignatureOfContext())
       TC.configureInterfaceType(FD);
 
     if (FD->isInvalid())
@@ -6127,7 +6146,7 @@
   /// Compute the interface type of the given enum element.
   void computeEnumElementInterfaceType(EnumElementDecl *elt) {
     auto enumDecl = cast<EnumDecl>(elt->getDeclContext());
-    assert(enumDecl->isGenericContext() && "Not a generic enum");
+    assert(enumDecl->getGenericSignatureOfContext() && "Not a generic enum");
 
     // Build the generic function type.
     auto funcTy = elt->getType()->castTo<AnyFunctionType>();
@@ -6223,7 +6242,7 @@
     // case the enclosing enum type was illegally declared inside of a generic
     // context. (In that case, we'll post a diagnostic while visiting the
     // parent enum.)
-    if (EED->getDeclContext()->isGenericContext())
+    if (EED->getDeclContext()->getGenericSignatureOfContext())
       computeEnumElementInterfaceType(EED);
 
     // Require the carried type to be materializable.
@@ -6384,7 +6403,8 @@
       gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext());
 
       if (TC.validateGenericFuncSignature(CD)) {
-        TC.markInvalidGenericSignature(CD);
+        auto *env = TC.markInvalidGenericSignature(CD);
+        CD->setGenericEnvironment(env);
       } else {
         ArchetypeBuilder builder =
           TC.createArchetypeBuilder(CD->getModuleContext());
@@ -6399,14 +6419,19 @@
         TC.revertGenericFuncSignature(CD);
 
         // Assign archetypes.
-        TC.finalizeGenericParamList(builder, gp, CD);
+        auto *env = TC.finalizeGenericParamList(builder, gp, nullptr, CD);
+        CD->setGenericEnvironment(env);
       }
-    } else if (CD->getDeclContext()->isGenericContext()) {
+    } else if (CD->getDeclContext()->getGenericSignatureOfContext()) {
       if (TC.validateGenericFuncSignature(CD)) {
-        TC.markInvalidGenericSignature(CD);
+        auto *env = TC.markInvalidGenericSignature(CD);
+        CD->setGenericEnvironment(env);
       } else {
         // Revert all of the types within the signature of the constructor.
         TC.revertGenericFuncSignature(CD);
+
+        CD->setGenericEnvironment(
+            CD->getDeclContext()->getGenericEnvironmentOfContext());
       }
     }
 
@@ -6419,7 +6444,7 @@
       configureConstructorType(CD, SelfTy,
                                CD->getParameterList(1)->getType(TC.Context));
 
-      if (!CD->isGenericContext())
+      if (!CD->getGenericSignatureOfContext())
         TC.configureInterfaceType(CD);
     }
 
@@ -6554,8 +6579,11 @@
 
     Type SelfTy = configureImplicitSelf(TC, DD);
 
-    if (DD->getDeclContext()->isGenericContext())
+    if (DD->getDeclContext()->getGenericSignatureOfContext()) {
       TC.validateGenericFuncSignature(DD);
+      DD->setGenericEnvironment(
+          DD->getDeclContext()->getGenericEnvironmentOfContext());
+    }
 
     if (semaFuncParamPatterns(DD)) {
       DD->overwriteType(ErrorType::get(TC.Context));
@@ -6563,7 +6591,7 @@
       DD->setInvalid();
     }
 
-    if (!DD->isGenericContext())
+    if (!DD->getGenericSignatureOfContext())
       TC.configureInterfaceType(DD);
 
     if (!DD->hasType()) {
@@ -7328,8 +7356,7 @@
 /// the parameter lists within the extension.
 static Type checkExtensionGenericParams(
               TypeChecker &tc, ExtensionDecl *ext,
-              Type type, GenericParamList *genericParams,
-              GenericSignature *&sig) {
+              Type type, GenericParamList *genericParams) {
   // Find the nominal type declaration and its parent type.
   Type parentType;
   NominalTypeDecl *nominal;
@@ -7352,8 +7379,7 @@
                       tc, ext, parentType,
                       nominal->getGenericParams()
                         ? genericParams->getOuterParameters()
-                        : genericParams,
-                      sig);
+                        : genericParams);
     if (!newParentType)
       return Type();
   }
@@ -7396,9 +7422,14 @@
 
   // Validate the generic type signature.
   bool invalid = false;
-  sig = tc.validateGenericSignature(genericParams, ext->getDeclContext(),
-                                    nullptr, inferExtendedTypeReqs, invalid);
+  GenericSignature *sig = tc.validateGenericSignature(
+      genericParams, ext->getDeclContext(),
+      nullptr, inferExtendedTypeReqs, invalid);
+  ext->setGenericSignature(sig);
+
   if (invalid) {
+    auto *env = tc.markInvalidGenericSignature(ext);
+    ext->setGenericEnvironment(env);
     return nullptr;
   }
 
@@ -7408,7 +7439,9 @@
   auto *parentSig = ext->getDeclContext()->getGenericSignatureOfContext();
   tc.checkGenericParamList(&builder, genericParams, parentSig);
   inferExtendedTypeReqs(builder);
-  tc.finalizeGenericParamList(builder, genericParams, ext);
+
+  auto *env = tc.finalizeGenericParamList(builder, genericParams, nullptr, ext);
+  ext->setGenericEnvironment(env);
 
   if (isa<ProtocolDecl>(nominal)) {
     // Retain type sugar if it's there.
@@ -7475,24 +7508,28 @@
     assert(genericParams && "bindExtensionDecl didn't set generic params?");
 
     // Check generic parameters.
-    GenericSignature *sig = nullptr;
     extendedType = checkExtensionGenericParams(*this, ext,
                                                ext->getExtendedType(),
-                                               ext->getGenericParams(),
-                                               sig);
+                                               ext->getGenericParams());
     if (!extendedType) {
       ext->setInvalid();
       ext->getExtendedTypeLoc().setInvalidType(Context);
       return;
     }
 
-    ext->setGenericSignature(sig);
     ext->getExtendedTypeLoc().setType(extendedType);
     return;
   }
 
   // If we're extending a protocol, check the generic parameters.
-  if (auto proto = extendedType->getAs<ProtocolType>()) {
+  //
+  // Canonicalize the type to work around the fact that getAs<> cannot
+  // "look through" protocol<X, Y> where X and Y both desugar to the same
+  // thing.
+  //
+  // FIXME: Probably the above comes up elsewhere, perhaps getAs<>()
+  // should be fixed.
+  if (auto proto = extendedType->getCanonicalType()->getAs<ProtocolType>()) {
     if (!isa<ProtocolType>(extendedType.getPointer()) &&
         proto->getDecl()->getParentModule() == ext->getParentModule()) {
       // Protocols in the same module cannot be extended via a typealias;
@@ -7505,18 +7542,14 @@
       return;
     }
 
-    GenericSignature *sig = nullptr;
-    extendedType = checkExtensionGenericParams(*this, ext,
-                                               ext->getExtendedType(),
-                                               ext->getGenericParams(),
-                                               sig);
+    extendedType = checkExtensionGenericParams(*this, ext, proto,
+                                               ext->getGenericParams());
     if (!extendedType) {
       ext->setInvalid();
       ext->getExtendedTypeLoc().setInvalidType(Context);
       return;
     }
 
-    ext->setGenericSignature(sig);
     ext->getExtendedTypeLoc().setType(extendedType);
 
     // Speculatively ban extension of AnyObject; it won't be a
@@ -7529,6 +7562,8 @@
     }
     return;
   }
+
+  assert(extendedType->is<NominalType>());
 }
 
 ArrayRef<ProtocolDecl *>
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 3ef2858..53a7964 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -471,33 +471,36 @@
   return resultType;
 }
 
-void TypeChecker::markInvalidGenericSignature(ValueDecl *VD) {
-  GenericParamList *genericParams;
-  if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD))
-    genericParams = AFD->getGenericParams();
-  else
-    genericParams = cast<GenericTypeDecl>(VD)->getGenericParams();
-
+GenericEnvironment *
+TypeChecker::markInvalidGenericSignature(DeclContext *DC) {
   // If there aren't any generic parameters at this level, we're done.
-  if (genericParams == nullptr)
-    return;
+  if (!DC->isInnermostContextGeneric())
+    return nullptr;
 
-  DeclContext *DC = VD->getDeclContext();
-  ArchetypeBuilder builder = createArchetypeBuilder(DC->getParentModule());
+  GenericParamList *genericParams = DC->getGenericParamsOfContext();
+  GenericSignature *genericSig = DC->getGenericSignatureOfContext();
 
-  if (auto sig = DC->getGenericSignatureOfContext())
-    builder.addGenericSignature(sig, true);
+  // Build new archetypes without any generic requirements.
+  DeclContext *parentDC = DC->getParent();
+  auto builder = createArchetypeBuilder(parentDC->getParentModule());
+
+  auto parentSig = parentDC->getGenericSignatureOfContext();
+
+  if (parentSig != nullptr)
+    builder.addGenericSignature(parentSig, true);
 
   // Visit each of the generic parameters.
   for (auto param : *genericParams)
     builder.addGenericParameter(param);
 
   // Wire up the archetypes.
+  auto genericEnv = builder.getGenericEnvironment(
+      genericSig->getGenericParams());
+
   for (auto GP : *genericParams)
     GP->setArchetype(builder.getArchetype(GP));
 
-  genericParams->setAllArchetypes(
-      Context.AllocateCopy(builder.getAllArchetypes()));
+  return genericEnv;
 }
 
 bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) {
@@ -540,7 +543,7 @@
   auto sig = builder.getGenericSignature(allGenericParams);
 
   // Debugging of the archetype builder and generic signature generation.
-  if (sig && Context.LangOpts.DebugGenericSignatures) {
+  if (Context.LangOpts.DebugGenericSignatures) {
     func->dumpRef(llvm::errs());
     llvm::errs() << "\n";
     builder.dump(llvm::errs());
@@ -789,9 +792,11 @@
 
 /// Finalize the given generic parameter list, assigning archetypes to
 /// the generic parameters.
-void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder,
-                                           GenericParamList *genericParams,
-                                           DeclContext *dc) {
+GenericEnvironment *
+TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder,
+                                      GenericParamList *genericParams,
+                                      GenericSignature *genericSig,
+                                      DeclContext *dc) {
   Accessibility access;
   if (auto *fd = dyn_cast<FuncDecl>(dc))
     access = fd->getFormalAccess();
@@ -802,14 +807,17 @@
   access = std::max(access, Accessibility::Internal);
 
   // Wire up the archetypes.
+  if (genericSig == nullptr)
+    genericSig = dc->getGenericSignatureOfContext();
+  auto genericEnv = builder.getGenericEnvironment(
+      genericSig->getGenericParams());
+
   for (auto GP : *genericParams) {
     GP->setArchetype(builder.getArchetype(GP));
     checkInheritanceClause(GP);
     if (!GP->hasAccessibility())
       GP->setAccessibility(access);
   }
-  genericParams->setAllArchetypes(
-    Context.AllocateCopy(builder.getAllArchetypes()));
 
 #ifndef NDEBUG
   // Record archetype contexts.
@@ -859,6 +867,8 @@
       break;
     }
   }
+
+  return genericEnv;
 }
 
 /// Revert the dependent types within the given generic parameter list.
@@ -903,13 +913,14 @@
   auto *gp = typeDecl->getGenericParams();
   auto *dc = typeDecl->getDeclContext();
 
-  auto sig = validateGenericSignature(gp, dc, nullptr, nullptr, invalid);
+  auto *sig = validateGenericSignature(gp, dc, nullptr, nullptr, invalid);
   assert(sig->getInnermostGenericParams().size()
            == typeDecl->getGenericParams()->size());
   typeDecl->setGenericSignature(sig);
 
   if (invalid) {
-    markInvalidGenericSignature(typeDecl);
+    auto *env = markInvalidGenericSignature(typeDecl);
+    typeDecl->setGenericEnvironment(env);
     return invalid;
   }
 
@@ -919,7 +930,9 @@
     createArchetypeBuilder(typeDecl->getModuleContext());
   auto *parentSig = dc->getGenericSignatureOfContext();
   checkGenericParamList(&builder, gp, parentSig);
-  finalizeGenericParamList(builder, gp, typeDecl);
+
+  auto *env = finalizeGenericParamList(builder, gp, nullptr, typeDecl);
+  typeDecl->setGenericEnvironment(env);
 
   return invalid;
 }
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index c9d4098..b0104cb 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -292,19 +292,12 @@
     // extension MyProtocol where Self : YourProtocol { ... }
     if (parentDC->getAsProtocolExtensionContext()) {
       auto ED = cast<ExtensionDecl>(parentDC);
-      if (auto genericParams = ED->getGenericParams()) {
-        for (auto req : genericParams->getTrailingRequirements()) {
-          // We might be resolving 'req.getSubject()' itself.
-          // This whole case feels like a hack -- there should be a
-          // more principled way to represent extensions of protocol
-          // compositions.
-          if (req.getKind() == RequirementReprKind::TypeConstraint) {
-            if (!req.getSubject() ||
-                !req.getSubject()->is<ArchetypeType>() ||
-                !req.getSubject()->castTo<ArchetypeType>()->getSelfProtocol())
-              continue;
-
-            stack.push_back(req.getConstraint());
+      if (auto genericSig = ED->getGenericSignature()) {
+        for (auto req : genericSig->getRequirements()) {
+          if (req.getKind() == RequirementKind::Conformance ||
+              req.getKind() == RequirementKind::Superclass) {
+            if (req.getFirstType()->isEqual(ED->getSelfInterfaceType()))
+              stack.push_back(req.getSecondType());
           }
         }
       }
@@ -2131,11 +2124,11 @@
   }
 
   // SIL uses polymorphic function types to resolve overloaded member functions.
-  if (auto genericParams = repr->getGenericParams()) {
+  if (auto genericEnv = repr->getGenericEnvironment()) {
     auto *genericSig = repr->getGenericSignature();
     assert(genericSig != nullptr && "Did not call handleSILGenericParams()?");
-    inputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericParams, inputTy);
-    outputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericParams, outputTy);
+    inputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, inputTy);
+    outputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, outputTy);
     return GenericFunctionType::get(genericSig, inputTy, outputTy, extInfo);
   }
 
@@ -2224,24 +2217,24 @@
   SmallVector<SILParameterInfo, 4> interfaceParams;
   SmallVector<SILResultInfo, 4> interfaceResults;
   Optional<SILResultInfo> interfaceErrorResult;
-  if (auto *genericParams = repr->getGenericParams()) {
+  if (auto *genericEnv = repr->getGenericEnvironment()) {
     genericSig = repr->getGenericSignature()->getCanonicalSignature();
  
     for (auto &param : params) {
       auto transParamType = ArchetypeBuilder::mapTypeOutOfContext(
-          M, genericParams, param.getType())->getCanonicalType();
+          M, genericEnv, param.getType())->getCanonicalType();
       interfaceParams.push_back(param.getWithType(transParamType));
     }
     for (auto &result : results) {
       auto transResultType =
         ArchetypeBuilder::mapTypeOutOfContext(
-          M, genericParams, result.getType())->getCanonicalType();
+          M, genericEnv, result.getType())->getCanonicalType();
       interfaceResults.push_back(result.getWithType(transResultType));
     }
 
     if (errorResult) {
       auto transErrorResultType = ArchetypeBuilder::mapTypeOutOfContext(
-          M, genericParams, errorResult->getType())->getCanonicalType();
+          M, genericEnv, errorResult->getType())->getCanonicalType();
       interfaceErrorResult =
         errorResult->getWithType(transErrorResultType);
     }
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index d3c5f2b..c938524 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -706,9 +706,10 @@
 }
 
 /// Expose TypeChecker's handling of GenericParamList to SIL parsing.
-GenericSignature *swift::handleSILGenericParams(ASTContext &Ctx,
-                                                GenericParamList *genericParams,
-                                                DeclContext *DC) {
+std::pair<GenericSignature *, GenericEnvironment *>
+swift::handleSILGenericParams(ASTContext &Ctx,
+                              GenericParamList *genericParams,
+                              DeclContext *DC) {
   return TypeChecker(Ctx).handleSILGenericParams(genericParams, DC);
 }
 
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 0694cb7..05b146a 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -731,8 +731,9 @@
   void checkUnsupportedProtocolType(Stmt *stmt);
 
   /// Expose TypeChecker's handling of GenericParamList to SIL parsing.
-  GenericSignature *handleSILGenericParams(GenericParamList *genericParams,
-                                           DeclContext *DC);
+  std::pair<GenericSignature *, GenericEnvironment *>
+  handleSILGenericParams(GenericParamList *genericParams,
+                         DeclContext *DC);
 
   /// \brief Resolves a TypeRepr to a type.
   ///
@@ -996,7 +997,7 @@
   bool isProtocolExtensionUsable(DeclContext *dc, Type type,
                                  ExtensionDecl *protocolExtension) override;
 
-  void markInvalidGenericSignature(ValueDecl *VD);
+  GenericEnvironment *markInvalidGenericSignature(DeclContext *dc);
 
   /// Configure the interface type of a function declaration.
   void configureInterfaceType(AbstractFunctionDecl *func);
@@ -1044,9 +1045,10 @@
 
   /// Finalize the given generic parameter list, assigning archetypes to
   /// the generic parameters.
-  void finalizeGenericParamList(ArchetypeBuilder &builder,
-                                GenericParamList *genericParams,
-                                DeclContext *dc);
+  GenericEnvironment *finalizeGenericParamList(ArchetypeBuilder &builder,
+                                               GenericParamList *genericParams,
+                                               GenericSignature *genericSig,
+                                               DeclContext *dc);
 
   /// Validate the signature of a generic type.
   ///
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 9e83da8..ff1ec85 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -15,6 +15,7 @@
 #include "swift/AST/AST.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/PrettyStackTrace.h"
 #include "swift/ClangImporter/ClangImporter.h"
 #include "swift/Parse/Parser.h"
@@ -633,8 +634,7 @@
 
 GenericParamList *
 ModuleFile::maybeGetOrReadGenericParams(serialization::DeclID genericContextID,
-                                        DeclContext *DC,
-                                        llvm::BitstreamCursor &Cursor) {
+                                        DeclContext *DC) {
   if (genericContextID) {
     Decl *genericContext = getDecl(genericContextID);
     assert(genericContext && "loading PolymorphicFunctionType before its decl");
@@ -647,93 +647,44 @@
       return ext->getGenericParams();
     llvm_unreachable("only functions and nominals can provide generic params");
   } else {
-    return maybeReadGenericParams(DC, Cursor);
+    return maybeReadGenericParams(DC);
   }
 }
 
 GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC,
-                                               llvm::BitstreamCursor &Cursor,
                                                GenericParamList *outerParams) {
   using namespace decls_block;
 
   assert(DC && "need a context for the decls in the list");
 
-  BCOffsetRAII lastRecordOffset(Cursor);
+  BCOffsetRAII lastRecordOffset(DeclTypeCursor);
   SmallVector<uint64_t, 8> scratch;
   StringRef blobData;
 
-  auto next = Cursor.advance(AF_DontPopBlockAtEnd);
+  auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
   if (next.Kind != llvm::BitstreamEntry::Record)
     return nullptr;
 
-  // Read the raw archetype IDs into a different scratch buffer
-  // because we need to keep this alive for longer.
-  SmallVector<uint64_t, 4> rawArchetypeIDsBuffer;
-  unsigned kind = Cursor.readRecord(next.ID, rawArchetypeIDsBuffer, &blobData);
+  unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData);
   if (kind != GENERIC_PARAM_LIST)
     return nullptr;
 
-  // Read in the raw-archetypes buffer, but don't try to consume it yet.
-  ArrayRef<uint64_t> rawArchetypeIDs;
-  GenericParamListLayout::readRecord(rawArchetypeIDsBuffer, rawArchetypeIDs);
-
   SmallVector<GenericTypeParamDecl *, 8> params;
   SmallVector<RequirementRepr, 8> requirements;
-  SmallVector<ArchetypeType *, 8> archetypes;
-
-  // The GenericTypeParamDecls might be from a different module file.
-  // If so, we need to map the archetype IDs from the serialized
-  // all-archetypes list in this module file over to the corresponding
-  // archetypes from the original generic parameter decls, or else
-  // we'll end up constructing fresh archetypes that don't match the
-  // ones from the generic parameters.
-
-  // We have to do this mapping before we might call getType on one of
-  // those archetypes, but after we've read all the generic parameters.
-  // Therefore we do it lazily.
-  bool haveMappedArchetypes = false;
-  auto mapArchetypes = [&] {
-    if (haveMappedArchetypes) return;
-
-    GenericParamList::deriveAllArchetypes(params, archetypes);
-    assert(rawArchetypeIDs.size() == archetypes.size());
-    for (unsigned index : indices(rawArchetypeIDs)) {
-      TypeID TID = rawArchetypeIDs[index];
-      auto &typeOrOffset = Types[TID-1];
-      if (typeOrOffset.isComplete()) {
-        // FIXME: this assertion is absolutely correct, but it's
-        // currently fouled up by the presence of archetypes in
-        // substitutions.  Those *should* be irrelevant for all the
-        // cases where this is wrong, but...
-
-        //assert(typeOrOffset.get().getPointer() == archetypes[index] &&
-        //       "already deserialized this archetype to a different type!");
-
-        // TODO: remove unsafeOverwrite when this hack goes away
-        typeOrOffset.unsafeOverwrite(archetypes[index]);
-      } else {
-        typeOrOffset = archetypes[index];
-      }
-    }
-
-    haveMappedArchetypes = true;
-  };
 
   while (true) {
     lastRecordOffset.reset();
     bool shouldContinue = true;
 
-    auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
+    auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
     if (entry.Kind != llvm::BitstreamEntry::Record)
       break;
 
     scratch.clear();
-    unsigned recordID = Cursor.readRecord(entry.ID, scratch,
+    unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
                                                   &blobData);
     switch (recordID) {
     case GENERIC_PARAM: {
-      assert(!haveMappedArchetypes &&
-             "generic parameters interleaved with requirements?");
       DeclID paramDeclID;
       GenericParamLayout::readRecord(scratch, paramDeclID);
       auto genericParam = cast<GenericTypeParamDecl>(getDecl(paramDeclID, DC));
@@ -760,8 +711,6 @@
       GenericRequirementLayout::readRecord(scratch, rawKind,
                                            rawTypeIDs[0], rawTypeIDs[1]);
 
-      mapArchetypes();
-
       switch (rawKind) {
       case GenericRequirementKind::Conformance: {
         auto subject = TypeLoc::withoutLoc(getType(rawTypeIDs[0]));
@@ -817,13 +766,9 @@
       break;
   }
 
-  // Make sure we map the archetypes if we haven't yet.
-  mapArchetypes();
-
   auto paramList = GenericParamList::create(getContext(), SourceLoc(),
                                             params, SourceLoc(), requirements,
                                             SourceLoc());
-  paramList->setAllArchetypes(getContext().AllocateCopy(archetypes));
   paramList->setOuterParameters(outerParams ? outerParams :
                                 DC->getGenericParamsOfContext());
 
@@ -847,8 +792,7 @@
       break;
 
     scratch.clear();
-    unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
-                                                  &blobData);
+    unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
     switch (recordID) {
     case GENERIC_REQUIREMENT: {
       uint8_t rawKind;
@@ -906,6 +850,78 @@
   }
 }
 
+GenericEnvironment *ModuleFile::readGenericEnvironment(
+    SmallVectorImpl<GenericTypeParamType *> &paramTypes,
+    llvm::BitstreamCursor &Cursor) {
+  using namespace decls_block;
+
+  BCOffsetRAII lastRecordOffset(Cursor);
+  SmallVector<uint64_t, 8> scratch;
+  StringRef blobData;
+
+  TypeSubstitutionMap interfaceToArchetypeMap;
+
+  while (true) {
+    lastRecordOffset.reset();
+    bool shouldContinue = true;
+
+    auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
+    if (entry.Kind != llvm::BitstreamEntry::Record)
+      break;
+
+    scratch.clear();
+    unsigned recordID = Cursor.readRecord(entry.ID, scratch, &blobData);
+    switch (recordID) {
+    case GENERIC_ENVIRONMENT: {
+      uint64_t rawTypeIDs[2];
+      GenericEnvironmentLayout::readRecord(scratch,
+                                           rawTypeIDs[0], rawTypeIDs[1]);
+
+      auto paramTy = getType(rawTypeIDs[0])->castTo<GenericTypeParamType>();
+      auto contextTy = getType(rawTypeIDs[1]);
+
+      auto result = interfaceToArchetypeMap.insert(
+          std::make_pair(paramTy, contextTy));
+
+      assert(result.second);
+      paramTypes.push_back(paramTy);
+      break;
+    }
+    default:
+      // This record is not part of the GenericEnvironment.
+      shouldContinue = false;
+      break;
+    }
+
+    if (!shouldContinue)
+      break;
+  }
+
+  if (interfaceToArchetypeMap.empty())
+    return nullptr;
+
+  return GenericEnvironment::get(getContext(), interfaceToArchetypeMap);
+}
+
+std::pair<GenericSignature *, GenericEnvironment *>
+ModuleFile::maybeReadGenericSignature() {
+  SmallVector<GenericTypeParamType *, 4> paramTypes;
+
+  // Read the generic environment.
+  auto env = readGenericEnvironment(paramTypes, DeclTypeCursor);
+
+  if (env == nullptr)
+    return std::make_pair(nullptr, nullptr);
+
+  // Read the generic requirements.
+  SmallVector<Requirement, 4> requirements;
+  readGenericRequirements(requirements);
+
+  auto sig = GenericSignature::get(paramTypes, requirements);
+
+  return std::make_pair(sig, env);
+}
+
 bool ModuleFile::readMembers(SmallVectorImpl<Decl *> &Members) {
   using namespace decls_block;
 
@@ -2150,7 +2166,7 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
+    auto genericParams = maybeReadGenericParams(DC);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
@@ -2160,18 +2176,14 @@
     declOrOffset = alias;
 
     if (genericParams) {
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *genericParams) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                               ->castTo<GenericTypeParamType>());
-      }
+      GenericSignature *sig;
+      GenericEnvironment *env;
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+      std::tie(sig, env) = maybeReadGenericSignature();
 
-      auto sig = GenericSignature::get(paramTypes, requirements);
+      assert(sig && "generic typealias without signature");
       alias->setGenericSignature(sig);
+      alias->setGenericEnvironment(env);
     }
 
     alias->computeType();
@@ -2294,7 +2306,7 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
+    auto genericParams = maybeReadGenericParams(DC);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
@@ -2312,20 +2324,14 @@
 
     if (isImplicit)
       theStruct->setImplicit();
-    if (genericParams) {
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *theStruct->getGenericParams()) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                               ->castTo<GenericTypeParamType>());
-      }
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+    GenericSignature *sig;
+    GenericEnvironment *env;
 
-      auto sig = GenericSignature::get(paramTypes, requirements);
-      theStruct->setGenericSignature(sig);
-    }
+    std::tie(sig, env) = maybeReadGenericSignature();
+
+    theStruct->setGenericSignature(sig);
+    theStruct->setGenericEnvironment(env);
 
     theStruct->computeType();
 
@@ -2362,10 +2368,13 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto genericParams = maybeReadGenericParams(parent, DeclTypeCursor);
+    auto *genericParams = maybeReadGenericParams(parent);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
+    SmallVector<GenericTypeParamType *, 2> genericParamTypes;
+    auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor);
+
     // Resolve the name ids.
     SmallVector<Identifier, 2> argNames;
     for (auto argNameID : argNameIDs)
@@ -2408,6 +2417,8 @@
       ctor->setInterfaceType(interfaceType);
     }
 
+    ctor->setGenericEnvironment(genericEnv);
+
     // Set the initializer interface type of the constructor.
     auto allocType = ctor->getInterfaceType();
     auto selfTy = ctor->computeInterfaceSelfType(/*isInitializingCtor=*/true);
@@ -2571,7 +2582,10 @@
     // Read generic params before reading the type, because the type may
     // reference generic parameters, and we want them to have a dummy
     // DeclContext for now.
-    GenericParamList *genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
+    GenericParamList *genericParams = maybeReadGenericParams(DC);
+
+    SmallVector<GenericTypeParamType *, 2> genericParamTypes;
+    auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor);
 
     auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling);
     if (!staticSpelling.hasValue()) {
@@ -2640,6 +2654,8 @@
       fn->setInterfaceType(interfaceType);
     }
 
+    fn->setGenericEnvironment(genericEnv);
+
     SmallVector<ParameterList*, 2> paramLists;
     for (unsigned i = 0, e = numParamPatterns; i != e; ++i)
       paramLists.push_back(readParameterList());
@@ -2752,21 +2768,16 @@
 
     handleInherited(proto, rawProtocolAndInheritedIDs.slice(numProtocols));
 
-    if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) {
+    if (auto genericParams = maybeReadGenericParams(DC))
       proto->setGenericParams(genericParams);
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *proto->getGenericParams()) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                               ->castTo<GenericTypeParamType>());
-      }
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+    GenericSignature *sig;
+    GenericEnvironment *env;
 
-      auto sig = GenericSignature::get(paramTypes, requirements);
-      proto->setGenericSignature(sig);
-    }
+    std::tie(sig, env) = maybeReadGenericSignature();
+
+    proto->setGenericSignature(sig);
+    proto->setGenericEnvironment(env);
 
     if (isImplicit)
       proto->setImplicit();
@@ -2919,7 +2930,7 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
+    auto genericParams = maybeReadGenericParams(DC);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
@@ -2940,20 +2951,15 @@
     theClass->setSuperclass(getType(superclassID));
     if (requiresStoredPropertyInits)
       theClass->setRequiresStoredPropertyInits(true);
-    if (genericParams) {
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *theClass->getGenericParams()) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                               ->castTo<GenericTypeParamType>());
-      }
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+    GenericSignature *sig;
+    GenericEnvironment *env;
 
-      GenericSignature *sig = GenericSignature::get(paramTypes, requirements);
-      theClass->setGenericSignature(sig);
-    }
+    std::tie(sig, env) = maybeReadGenericSignature();
+
+    theClass->setGenericSignature(sig);
+    theClass->setGenericEnvironment(env);
+
     theClass->computeType();
 
     handleInherited(theClass, rawInheritedIDs);
@@ -2987,7 +2993,7 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
+    auto genericParams = maybeReadGenericParams(DC);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
@@ -3006,20 +3012,14 @@
     if (isImplicit)
       theEnum->setImplicit();
     theEnum->setRawType(getType(rawTypeID));
-    if (genericParams) {
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *theEnum->getGenericParams()) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                               ->castTo<GenericTypeParamType>());
-      }
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+    GenericSignature *sig;
+    GenericEnvironment *env;
 
-      GenericSignature *sig = GenericSignature::get(paramTypes, requirements);
-      theEnum->setGenericSignature(sig);
-    }
+    std::tie(sig, env) = maybeReadGenericSignature();
+
+    theEnum->setGenericSignature(sig);
+    theEnum->setGenericEnvironment(env);
 
     theEnum->computeType();
 
@@ -3198,28 +3198,16 @@
     extension->setCheckedInheritanceClause();
 
     // Generic parameters.
-    GenericParamList *genericParams = maybeReadGenericParams(DC,
-                                                             DeclTypeCursor);
+    GenericParamList *genericParams = maybeReadGenericParams(DC);
     extension->setGenericParams(genericParams);
 
-    // Conjure up a generic signature from the generic parameters and
-    // requirements.
-    if (genericParams) {
-      SmallVector<GenericTypeParamType *, 4> paramTypes;
-      for (auto &genericParam : *genericParams) {
-        paramTypes.push_back(genericParam->getDeclaredType()
-                             ->castTo<GenericTypeParamType>());
-      }
+    GenericSignature *sig;
+    GenericEnvironment *env;
 
-      // Read the generic requirements.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements);
+    std::tie(sig, env) = maybeReadGenericSignature();
 
-      if (!paramTypes.empty()) {
-        GenericSignature *sig = GenericSignature::get(paramTypes, requirements);
-        extension->setGenericSignature(sig);
-      }
-    }
+    extension->setGenericSignature(sig);
+    extension->setGenericEnvironment(env);
 
     extension->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
     skipRecord(DeclTypeCursor, decls_block::MEMBERS);
@@ -3266,6 +3254,8 @@
       dtor->setGenericSignature(genericFnType->getGenericSignature());
     dtor->setInterfaceType(interfaceType);
 
+    dtor->setGenericEnvironment(DC->getGenericEnvironmentOfContext());
+
     if (isImplicit)
       dtor->setImplicit();
 
@@ -3846,7 +3836,7 @@
                                                            rawRep,
                                                            throws);
     GenericParamList *paramList =
-      maybeGetOrReadGenericParams(genericContextID, FileContext, DeclTypeCursor);
+      maybeGetOrReadGenericParams(genericContextID, FileContext);
     assert(paramList && "missing generic params for polymorphic function");
     
     auto rep = getActualFunctionTypeRepresentation(rawRep);
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 64fcf9b..31a3bbf 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -490,34 +490,18 @@
     fn->addSpecializeAttr(SILSpecializeAttr::create(SILMod, Substitutions));
   }
 
-  GenericParamList *contextParams = nullptr;
+  GenericEnvironment *genericEnv = nullptr;
   if (!declarationOnly) {
-    // We need to construct a linked list of GenericParamList. The outermost
-    // list appears first in the module file. Force the declaration's context to
-    // be the current module, not the original module associated with this
-    // module file. A generic param decl at module scope cannot refer to another
-    // module because we would have no way lookup the original module when
-    // serializing a copy of the function. This comes up with generic
-    // reabstraction thunks which have shared linkage.
-    DeclContext *outerParamContext = SILMod.getSwiftModule();
-    while (true) {
-      // Params' OuterParameters will point to contextParams.
-      auto *Params = MF->maybeReadGenericParams(outerParamContext,
-                                                SILCursor, contextParams);
-      if (!Params)
-        break;
-      // contextParams will point to the last deserialized list, which is the
-      // innermost one.
-      contextParams = Params;
-    }
+    SmallVector<GenericTypeParamType *, 4> genericParamTypes;
+    genericEnv = MF->readGenericEnvironment(genericParamTypes, SILCursor);
   }
 
   // If the next entry is the end of the block, then this function has
   // no contents.
   entry = SILCursor.advance(AF_DontPopBlockAtEnd);
   bool isEmptyFunction = (entry.Kind == llvm::BitstreamEntry::EndBlock);
-  assert((!isEmptyFunction || !contextParams) &&
-         "context params without body?!");
+  assert((!isEmptyFunction || !genericEnv) &&
+         "generic environment without body?!");
 
   // Remember this in our cache in case it's a recursive function.
   // Increase the reference count to keep it alive.
@@ -536,10 +520,10 @@
 
   NumDeserializedFunc++;
 
-  assert(!(fn->getContextGenericParams() && !fn->empty())
+  assert(!(fn->getGenericEnvironment() && !fn->empty())
          && "function already has context generic params?!");
-  if (contextParams)
-    fn->setContextGenericParams(contextParams);
+  if (genericEnv)
+    fn->setGenericEnvironment(genericEnv);
 
   scratch.clear();
   kind = SILCursor.readRecord(entry.ID, scratch);
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index f67b222..842116a 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -16,6 +16,7 @@
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/DiagnosticsCommon.h"
 #include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/LinkLibrary.h"
 #include "swift/AST/Mangle.h"
 #include "swift/AST/RawComment.h"
@@ -527,6 +528,8 @@
                               decls_block::GENERIC_REQUIREMENT);
   BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                               decls_block::LAST_GENERIC_REQUIREMENT);
+  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
+                              decls_block::GENERIC_ENVIRONMENT);
 
   BLOCK(SIL_INDEX_BLOCK);
   BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES);
@@ -931,7 +934,7 @@
 #undef CASE
 }
 
-void Serializer::writeRequirements(ArrayRef<Requirement> requirements) {
+void Serializer::writeGenericRequirements(ArrayRef<Requirement> requirements) {
   using namespace decls_block;
 
   if (requirements.empty())
@@ -948,29 +951,23 @@
   }
 }
 
-bool Serializer::writeGenericParams(const GenericParamList *genericParams,
-                                  const std::array<unsigned, 256> &abbrCodes) {
+bool Serializer::writeGenericParams(const GenericParamList *genericParams) {
   using namespace decls_block;
 
   // Don't write anything if there are no generic params.
   if (!genericParams)
     return true;
 
-  SmallVector<TypeID, 8> archetypeIDs;
-  for (auto archetype : genericParams->getAllArchetypes())
-    archetypeIDs.push_back(addTypeRef(archetype));
+  unsigned abbrCode = DeclTypeAbbrCodes[GenericParamListLayout::Code];
+  GenericParamListLayout::emitRecord(Out, ScratchRecord, abbrCode);
 
-  unsigned abbrCode = abbrCodes[GenericParamListLayout::Code];
-  GenericParamListLayout::emitRecord(Out, ScratchRecord, abbrCode,
-                                     archetypeIDs);
-
-  abbrCode = abbrCodes[GenericParamLayout::Code];
+  abbrCode = DeclTypeAbbrCodes[GenericParamLayout::Code];
   for (auto next : genericParams->getParams()) {
     GenericParamLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                    addDeclRef(next));
   }
 
-  abbrCode = abbrCodes[GenericRequirementLayout::Code];
+  abbrCode = DeclTypeAbbrCodes[GenericRequirementLayout::Code];
   SmallString<64> ReqStr;
   for (auto next : genericParams->getRequirements()) {
     ReqStr.clear();
@@ -996,12 +993,37 @@
     }
   }
 
-  abbrCode = abbrCodes[LastGenericRequirementLayout::Code];
+  abbrCode = DeclTypeAbbrCodes[LastGenericRequirementLayout::Code];
   uint8_t dummy = 0;
   LastGenericRequirementLayout::emitRecord(Out, ScratchRecord, abbrCode, dummy);
   return true;
 }
 
+void Serializer::writeGenericEnvironment(GenericSignature *sig,
+                                         GenericEnvironment *env,
+                                  const std::array<unsigned, 256> &abbrCodes) {
+  using namespace decls_block;
+
+  if (env == nullptr)
+    return;
+
+  auto &map = env->getInterfaceToArchetypeMap();
+
+  auto envAbbrCode = abbrCodes[GenericEnvironmentLayout::Code];
+
+  // Iterate over the signature's generic parameters, for stable
+  // iteration order.
+  for (auto *paramTy : sig->getGenericParams()) {
+    auto found = map.find(paramTy->getCanonicalType().getPointer());
+    assert(found != map.end() && "missing generic parameter");
+    auto contextTy = found->second;
+    GenericEnvironmentLayout::emitRecord(
+      Out, ScratchRecord, envAbbrCode,
+      addTypeRef(paramTy),
+      addTypeRef(contextTy));
+  }
+}
+
 void Serializer::writeNormalConformance(
        const NormalProtocolConformance *conformance) {
   using namespace decls_block;
@@ -1363,7 +1385,7 @@
         genericParams);
 
     if (genericSig) {
-      writeRequirements(genericSig->getRequirements());
+      writeGenericRequirements(genericSig->getRequirements());
     }
     break;
   }
@@ -2063,8 +2085,11 @@
                          isa<ProtocolDecl>(baseNominal);
     }
 
-    writeGenericParams(extension->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(extension->getGenericRequirements());
+    writeGenericParams(extension->getGenericParams());
+    writeGenericEnvironment(extension->getGenericSignature(),
+                            extension->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(extension->getGenericRequirements());
     writeMembers(extension->getMembers(), isClassExtension);
     writeConformances(conformances, DeclTypeAbbrCodes);
 
@@ -2184,8 +2209,11 @@
                                 addTypeRef(typeAlias->getInterfaceType()),
                                 typeAlias->isImplicit(),
                                 rawAccessLevel);
-    writeGenericParams(typeAlias->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(typeAlias->getGenericRequirements());
+    writeGenericParams(typeAlias->getGenericParams());
+    writeGenericEnvironment(typeAlias->getGenericSignature(),
+                            typeAlias->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(typeAlias->getGenericRequirements());
     break;
   }
 
@@ -2260,8 +2288,11 @@
                              inheritedTypes);
 
 
-    writeGenericParams(theStruct->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(theStruct->getGenericRequirements());
+    writeGenericParams(theStruct->getGenericParams());
+    writeGenericEnvironment(theStruct->getGenericSignature(),
+                            theStruct->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(theStruct->getGenericRequirements());
     writeMembers(theStruct->getMembers(), false);
     writeConformances(conformances, DeclTypeAbbrCodes);
     break;
@@ -2294,8 +2325,11 @@
                             conformances.size(),
                             inheritedTypes);
 
-    writeGenericParams(theEnum->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(theEnum->getGenericRequirements());
+    writeGenericParams(theEnum->getGenericParams());
+    writeGenericEnvironment(theEnum->getGenericSignature(),
+                            theEnum->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(theEnum->getGenericRequirements());
     writeMembers(theEnum->getMembers(), false);
     writeConformances(conformances, DeclTypeAbbrCodes);
     break;
@@ -2331,8 +2365,11 @@
                             conformances.size(),
                             inheritedTypes);
 
-    writeGenericParams(theClass->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(theClass->getGenericRequirements());
+    writeGenericParams(theClass->getGenericParams());
+    writeGenericEnvironment(theClass->getGenericSignature(),
+                            theClass->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(theClass->getGenericRequirements());
     writeMembers(theClass->getMembers(), true);
     writeConformances(conformances, DeclTypeAbbrCodes);
     break;
@@ -2367,8 +2404,11 @@
                                numProtocols,
                                protocolsAndInherited);
 
-    writeGenericParams(proto->getGenericParams(), DeclTypeAbbrCodes);
-    writeRequirements(proto->getGenericRequirements());
+    writeGenericParams(proto->getGenericParams());
+    writeGenericEnvironment(proto->getGenericSignature(),
+                            proto->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+    writeGenericRequirements(proto->getGenericRequirements());
     writeMembers(proto->getMembers(), true);
     writeDefaultWitnessTable(proto, DeclTypeAbbrCodes);
     break;
@@ -2468,7 +2508,10 @@
                            rawAccessLevel,
                            nameComponents);
 
-    writeGenericParams(fn->getGenericParams(), DeclTypeAbbrCodes);
+    writeGenericParams(fn->getGenericParams());
+    writeGenericEnvironment(fn->getGenericSignature(),
+                            fn->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
 
     // Write the body parameters.
     for (auto pattern : fn->getParameterLists())
@@ -2585,7 +2628,11 @@
                                   rawAccessLevel,
                                   nameComponents);
 
-    writeGenericParams(ctor->getGenericParams(), DeclTypeAbbrCodes);
+    writeGenericParams(ctor->getGenericParams());
+    writeGenericEnvironment(ctor->getGenericSignature(),
+                            ctor->getGenericEnvironment(),
+                            DeclTypeAbbrCodes);
+
     assert(ctor->getParameterLists().size() == 2);
     // Why is this writing out the param list for self?
     for (auto paramList : ctor->getParameterLists())
@@ -2961,7 +3008,7 @@
             getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
             fnTy->throws());
     if (!genericContext)
-      writeGenericParams(&fnTy->getGenericParams(), DeclTypeAbbrCodes);
+      writeGenericParams(&fnTy->getGenericParams());
     break;
   }
 
@@ -2979,7 +3026,7 @@
             genericParams);
 
     // Write requirements.
-    writeRequirements(fnTy->getRequirements());
+    writeGenericRequirements(fnTy->getRequirements());
     break;
   }
       
@@ -3045,9 +3092,7 @@
           fnTy->getNumAllResults(),
           variableData);
     if (sig)
-      writeRequirements(sig->getRequirements());
-    else
-      writeRequirements({});
+      writeGenericRequirements(sig->getRequirements());
     break;
   }
       
@@ -3243,6 +3288,7 @@
   registerDeclTypeAbbr<GenericParamLayout>();
   registerDeclTypeAbbr<GenericRequirementLayout>();
   registerDeclTypeAbbr<LastGenericRequirementLayout>();
+  registerDeclTypeAbbr<GenericEnvironmentLayout>();
 
   registerDeclTypeAbbr<ForeignErrorConventionLayout>();
   registerDeclTypeAbbr<DeclContextLayout>();
diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h
index 6b5e05c..7f4ae2c 100644
--- a/lib/Serialization/Serialization.h
+++ b/lib/Serialization/Serialization.h
@@ -241,8 +241,11 @@
   /// Writes the given pattern, recursively.
   void writePattern(const Pattern *pattern);
 
+  /// Writes a generic parameter list.
+  bool writeGenericParams(const GenericParamList *genericParams);
+
   /// Writes a set of generic requirements.
-  void writeRequirements(ArrayRef<Requirement> requirements);
+  void writeGenericRequirements(ArrayRef<Requirement> requirements);
 
   /// Writes a list of protocol conformances.
   void writeConformances(ArrayRef<ProtocolConformanceRef> conformances,
@@ -411,9 +414,10 @@
   void writeConformance(ProtocolConformance *conformance,
                         const std::array<unsigned, 256> &abbrCodes);
 
-  /// Writes a generic parameter list.
-  bool writeGenericParams(const GenericParamList *genericParams,
-                          const std::array<unsigned, 256> &abbrCodes);
+  /// Writes a generic environment.
+  void writeGenericEnvironment(GenericSignature *sig,
+                               GenericEnvironment *env,
+                         const std::array<unsigned, 256> &abbrCodes);
 
 };
 } // end namespace serialization
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 90ec7f4..d483902 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -374,15 +374,9 @@
 
   // Write the body's context archetypes, unless we don't actually have a body.
   if (!F.isExternalDeclaration()) {
-    if (auto gp = F.getContextGenericParams()) {
-      // To help deserializing the context generic params, we serialize the
-      // outer-most list first. In most cases, we do not have decls associated
-      // with these parameter lists, so serialize the lists directly.
-      std::vector<GenericParamList *> paramLists;
-      for (; gp; gp = gp->getOuterParameters())
-        paramLists.push_back(gp);
-      for (unsigned i = 0, e = paramLists.size(); i < e; i++)
-        S.writeGenericParams(paramLists.rbegin()[i], SILAbbrCodes);
+    if (auto genericEnv = F.getGenericEnvironment()) {
+      auto genericSig = F.getLoweredFunctionType()->getGenericSignature();
+      S.writeGenericEnvironment(genericSig, genericEnv, SILAbbrCodes);
     }
   }
 
@@ -1850,10 +1844,8 @@
   registerSILAbbr<decls_block::InheritedProtocolConformanceLayout>();
   registerSILAbbr<decls_block::NormalProtocolConformanceIdLayout>();
   registerSILAbbr<decls_block::ProtocolConformanceXrefLayout>();
-  registerSILAbbr<decls_block::GenericParamListLayout>();
-  registerSILAbbr<decls_block::GenericParamLayout>();
   registerSILAbbr<decls_block::GenericRequirementLayout>();
-  registerSILAbbr<decls_block::LastGenericRequirementLayout>();
+  registerSILAbbr<decls_block::GenericEnvironmentLayout>();
 
   for (const SILGlobalVariable &g : SILMod->getSILGlobals())
     writeSILGlobalVar(g);
diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt
index 47d7b24..f4bfd98 100644
--- a/stdlib/public/Platform/CMakeLists.txt
+++ b/stdlib/public/Platform/CMakeLists.txt
@@ -36,70 +36,72 @@
 
 set(glibc_modulemap_target_list)
 foreach(sdk ${SWIFT_SDKS})
-  if("${sdk}" STREQUAL "LINUX" OR
-     "${sdk}" STREQUAL "FREEBSD" OR
-     "${sdk}" STREQUAL "ANDROID" OR
-     "${sdk}" STREQUAL "CYGWIN")
-    foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
-      set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
-      set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}")
-      
-      # Determine the location of glibc headers based on the target.
-      set(GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH "/usr/include")
-      set(GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH ${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH})
-      
-      # Some SDKs place their headers in architecture-specific subfolders.
-      if((${sdk} STREQUAL "LINUX" OR ${sdk} STREQUAL "FREEBSD") AND CMAKE_LIBRARY_ARCHITECTURE)
-        set(GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH "${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}/${CMAKE_LIBRARY_ARCHITECTURE}")
-      endif()
+  if(NOT "${sdk}" STREQUAL "LINUX" AND
+     NOT "${sdk}" STREQUAL "FREEBSD" AND
+     NOT "${sdk}" STREQUAL "ANDROID" AND
+     NOT "${sdk}" STREQUAL "CYGWIN")
+    continue()
+  endif()
 
-      set(GLIBC_INCLUDE_PATH "${SWIFT_SDK_${sdk}_PATH}/${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH}")
-      set(GLIBC_ARCH_INCLUDE_PATH "${SWIFT_SDK_${sdk}_PATH}/${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}")
+  foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
+    set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
+    set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}")
 
-      set(glibc_modulemap_source "glibc.modulemap.gyb")
-      set(glibc_modulemap_out "${module_dir}/glibc.modulemap")
+    # Determine the location of glibc headers based on the target.
+    set(GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH "/usr/include")
+    set(GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH ${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH})
 
-      # Configure the module map based on the target. Each platform needs to
-      # reference different headers, based on what's available in their glibc.
-      # This is the 'glibc.modulemap' in the 'resource-dir', so 
-      # it's the one we'll look at during the build process.
-      handle_gyb_source_single(glibc_modulemap_target
+    # Some SDKs place their headers in architecture-specific subfolders.
+    if((${sdk} STREQUAL "LINUX" OR ${sdk} STREQUAL "FREEBSD") AND CMAKE_LIBRARY_ARCHITECTURE)
+      set(GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH "${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}/${CMAKE_LIBRARY_ARCHITECTURE}")
+    endif()
+
+    set(GLIBC_INCLUDE_PATH "${SWIFT_SDK_${sdk}_PATH}/${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH}")
+    set(GLIBC_ARCH_INCLUDE_PATH "${SWIFT_SDK_${sdk}_PATH}/${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}")
+
+    set(glibc_modulemap_source "glibc.modulemap.gyb")
+    set(glibc_modulemap_out "${module_dir}/glibc.modulemap")
+
+    # Configure the module map based on the target. Each platform needs to
+    # reference different headers, based on what's available in their glibc.
+    # This is the 'glibc.modulemap' in the 'resource-dir', so
+    # it's the one we'll look at during the build process.
+    handle_gyb_source_single(glibc_modulemap_target
+        SOURCE "${glibc_modulemap_source}"
+        OUTPUT "${glibc_modulemap_out}"
+        FLAGS
+            "-DCMAKE_SDK=${sdk}"
+            "-DGLIBC_INCLUDE_PATH=${GLIBC_INCLUDE_PATH}"
+            "-DGLIBC_ARCH_INCLUDE_PATH=${GLIBC_ARCH_INCLUDE_PATH}")
+
+    list(APPEND glibc_modulemap_target_list ${glibc_modulemap_target})
+
+    # If this SDK is a target for a non-native host, create a native modulemap
+    # without a sysroot prefix. This is the one we'll install instead.
+    if(NOT "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_PATH}" STREQUAL "/")
+
+      set(glibc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/glibc.modulemap")
+      handle_gyb_source_single(glibc_modulemap_native_target
           SOURCE "${glibc_modulemap_source}"
-          OUTPUT "${glibc_modulemap_out}"
+          OUTPUT "${glibc_sysroot_relative_modulemap_out}"
           FLAGS
               "-DCMAKE_SDK=${sdk}"
-              "-DGLIBC_INCLUDE_PATH=${GLIBC_INCLUDE_PATH}"
-              "-DGLIBC_ARCH_INCLUDE_PATH=${GLIBC_ARCH_INCLUDE_PATH}")
+              "-DGLIBC_INCLUDE_PATH=${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH}"
+              "-DGLIBC_ARCH_INCLUDE_PATH=${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}")
 
-      list(APPEND glibc_modulemap_target_list ${glibc_modulemap_target})
+      list(APPEND glibc_modulemap_target_list ${glibc_modulemap_native_target})
+      set(glibc_modulemap_out ${glibc_sysroot_relative_modulemap_out})
+    endif()
 
-      # If this SDK is a target for a non-native host, create a native modulemap 
-      # without a sysroot prefix. This is the one we'll install instead.
-      if(NOT "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_PATH}" STREQUAL "/")
+    # FIXME: When SDK is a cross-compile target (SDK != Host), the generated
+    #        modulemap will be relative to the Host, with hardcoded paths.
+    #        It is not relocatable to the target platform itself.
+    #        This only affects ANDROID right now, but could affect cross-compiled LINUX targets
 
-        set(glibc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/glibc.modulemap")
-        handle_gyb_source_single(glibc_modulemap_native_target
-            SOURCE "${glibc_modulemap_source}"
-            OUTPUT "${glibc_sysroot_relative_modulemap_out}"
-            FLAGS
-                "-DCMAKE_SDK=${sdk}"
-                "-DGLIBC_INCLUDE_PATH=${GLIBC_SYSROOT_RELATIVE_INCLUDE_PATH}"
-                "-DGLIBC_ARCH_INCLUDE_PATH=${GLIBC_SYSROOT_RELATIVE_ARCH_INCLUDE_PATH}")
+    swift_install_in_component(sdk-overlay
+        FILES "${glibc_modulemap_out}"
+        DESTINATION "lib/swift/${arch_subdir}")
 
-        list(APPEND glibc_modulemap_target_list ${glibc_modulemap_native_target})
-        set(glibc_modulemap_out ${glibc_sysroot_relative_modulemap_out})
-      endif()
-
-      # FIXME: When SDK is a cross-compile target (SDK != Host), the generated
-      #        modulemap will be relative to the Host, with hardcoded paths.
-      #        It is not relocatable to the target platform itself.
-      #        This only affects ANDROID right now, but could affect cross-compiled LINUX targets
-        
-      swift_install_in_component(sdk-overlay
-          FILES "${glibc_modulemap_out}"
-          DESTINATION "lib/swift/${arch_subdir}")
-
-    endforeach()
-  endif()
+  endforeach()
 endforeach()
 add_custom_target(glibc_modulemap DEPENDS ${glibc_modulemap_target_list})
diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift
index cff0d5e..34f18fc 100644
--- a/test/SILGen/witnesses.swift
+++ b/test/SILGen/witnesses.swift
@@ -426,14 +426,14 @@
 struct GenericParameterNameCollision<T: HasAssoc> :
     GenericParameterNameCollisionProtocol {
 
-  // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}foo{{.*}} : $@convention(witness_method) <T1 where T1 : HasAssoc><T> (@in T, @in_guaranteed GenericParameterNameCollision<T1>) -> () {
-  // CHECK:       bb0(%0 : $*T, %1 : $*GenericParameterNameCollision<T1>):
-  // CHECK:         apply {{%.*}}<T1, T1.Assoc, T>
+  // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}foo{{.*}} : $@convention(witness_method) <T where T : HasAssoc><T1> (@in T1, @in_guaranteed GenericParameterNameCollision<T>) -> () {
+  // CHECK:       bb0(%0 : $*T1, %1 : $*GenericParameterNameCollision<T>):
+  // CHECK:         apply {{%.*}}<T, T.Assoc, T1>
   func foo<U>(_ x: U) {}
 
-  // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}bar{{.*}} : $@convention(witness_method) <T1 where T1 : HasAssoc><T> (@owned @callee_owned (@in T) -> @out T1.Assoc, @in_guaranteed GenericParameterNameCollision<T1>) -> () {
-  // CHECK:       bb0(%0 : $@callee_owned (@in T) -> @out T1.Assoc, %1 : $*GenericParameterNameCollision<T1>):
-  // CHECK:         apply {{%.*}}<T1, T1.Assoc, T>
+  // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}bar{{.*}} : $@convention(witness_method) <T where T : HasAssoc><T1> (@owned @callee_owned (@in T1) -> @out T.Assoc, @in_guaranteed GenericParameterNameCollision<T>) -> () {
+  // CHECK:       bb0(%0 : $@callee_owned (@in T1) -> @out T.Assoc, %1 : $*GenericParameterNameCollision<T>):
+  // CHECK:         apply {{%.*}}<T, T.Assoc, T1>
   func bar<V>(_ x: (V) -> T.Assoc) {}
 }
 
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index ad75a79..902b9fe 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_swift_executable(swift
+add_swift_host_tool(swift
   api_notes.cpp
   driver.cpp
   autolink_extract_main.cpp
@@ -9,6 +9,7 @@
     swiftFrontendTool
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+  SWIFT_COMPONENT compiler
 )
 
 target_link_libraries(swift edit)
@@ -46,9 +47,6 @@
 endif()
 
 swift_install_in_component(compiler
-    TARGETS swift
-    RUNTIME DESTINATION "bin")
-swift_install_in_component(compiler
     FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swiftc"
     DESTINATION "bin")
 swift_install_in_component(autolink-driver
diff --git a/tools/lldb-moduleimport-test/CMakeLists.txt b/tools/lldb-moduleimport-test/CMakeLists.txt
index 6c9cfdb..f1c8082 100644
--- a/tools/lldb-moduleimport-test/CMakeLists.txt
+++ b/tools/lldb-moduleimport-test/CMakeLists.txt
@@ -1,12 +1,9 @@
-add_swift_executable(lldb-moduleimport-test
+add_swift_host_tool(lldb-moduleimport-test
   lldb-moduleimport-test.cpp
   LINK_LIBRARIES
     swiftASTSectionImporter swiftFrontend swiftClangImporter
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+  SWIFT_COMPONENT testsuite-tools
 )
 
-swift_install_in_component(testsuite-tools
-    TARGETS lldb-moduleimport-test
-    RUNTIME DESTINATION "bin")
-
diff --git a/tools/sil-extract/CMakeLists.txt b/tools/sil-extract/CMakeLists.txt
index 64be37c..982cdb1 100644
--- a/tools/sil-extract/CMakeLists.txt
+++ b/tools/sil-extract/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_swift_executable(sil-extract
+add_swift_host_tool(sil-extract
   SILExtract.cpp
   LINK_LIBRARIES
     swiftFrontend
@@ -8,9 +8,5 @@
     swiftClangImporter
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+  SWIFT_COMPONENT tools
 )
-
-swift_install_in_component(tools
-    TARGETS sil-extract
-    RUNTIME DESTINATION "bin")
-
diff --git a/tools/sil-opt/CMakeLists.txt b/tools/sil-opt/CMakeLists.txt
index fb5da2a..f2ccbb8 100644
--- a/tools/sil-opt/CMakeLists.txt
+++ b/tools/sil-opt/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_swift_executable(sil-opt
+add_swift_host_tool(sil-opt
   SILOpt.cpp
   LINK_LIBRARIES
     swiftFrontend
@@ -7,9 +7,5 @@
     swiftSILOptimizer
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+  SWIFT_COMPONENT tools
 )
-
-swift_install_in_component(tools
-    TARGETS sil-opt
-    RUNTIME DESTINATION bin)
-
diff --git a/tools/swift-demangle/CMakeLists.txt b/tools/swift-demangle/CMakeLists.txt
index ddb70af..7cefe19 100644
--- a/tools/swift-demangle/CMakeLists.txt
+++ b/tools/swift-demangle/CMakeLists.txt
@@ -1,9 +1,6 @@
-add_swift_executable(swift-demangle
+add_swift_host_tool(swift-demangle
   swift-demangle.cpp
   LINK_LIBRARIES swiftBasic
-  LLVM_COMPONENT_DEPENDS support)
-
-swift_install_in_component(compiler
-    TARGETS swift-demangle
-    RUNTIME DESTINATION "bin")
-
+  LLVM_COMPONENT_DEPENDS support
+  SWIFT_COMPONENT compiler
+  )
diff --git a/tools/swift-ide-test/CMakeLists.txt b/tools/swift-ide-test/CMakeLists.txt
index 9d44b4d..eedd3ce 100644
--- a/tools/swift-ide-test/CMakeLists.txt
+++ b/tools/swift-ide-test/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_swift_executable(swift-ide-test
+add_swift_host_tool(swift-ide-test
   swift-ide-test.cpp
   ModuleAPIDiff.cpp
   XMLValidator.cpp
@@ -8,6 +8,7 @@
     swiftIDE
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+  SWIFT_COMPONENT tools
 )
 
 # If libxml2 is available, make it available for swift-ide-test.
@@ -17,11 +18,6 @@
   add_definitions(-DSWIFT_HAVE_LIBXML="1")
 endif()
 
-swift_install_in_component(tools
-    TARGETS swift-ide-test
-    RUNTIME DESTINATION bin)
-
-
 # Create a symlink for swift-api-dump.py in the bin directory
 add_custom_command(TARGET swift-ide-test POST_BUILD
     COMMAND
diff --git a/tools/swift-llvm-opt/CMakeLists.txt b/tools/swift-llvm-opt/CMakeLists.txt
index 1b76f40..628d7bd 100644
--- a/tools/swift-llvm-opt/CMakeLists.txt
+++ b/tools/swift-llvm-opt/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_swift_executable(swift-llvm-opt
+add_swift_host_tool(swift-llvm-opt
   LLVMOpt.cpp
   LINK_LIBRARIES
   swiftIRGen
@@ -13,9 +13,6 @@
 
   LLVM_COMPONENT_DEPENDS
     DebugInfoCodeView
+
+  SWIFT_COMPONENT tools
 )
-
-swift_install_in_component(tools
-    TARGETS swift-llvm-opt
-    RUNTIME DESTINATION bin)
-
diff --git a/tools/swift-reflection-dump/CMakeLists.txt b/tools/swift-reflection-dump/CMakeLists.txt
index c24edf3..2cdcda1 100644
--- a/tools/swift-reflection-dump/CMakeLists.txt
+++ b/tools/swift-reflection-dump/CMakeLists.txt
@@ -1,11 +1,7 @@
-add_swift_executable(swift-reflection-dump
+add_swift_host_tool(swift-reflection-dump
   swift-reflection-dump.cpp
   LINK_FAT_LIBRARIES
     swiftReflection
   LLVM_COMPONENT_DEPENDS object support
+  SWIFT_COMPONENT tools
 )
-
-swift_install_in_component(tools
-    TARGETS swift-reflection-dump
-    RUNTIME DESTINATION bin)
-
diff --git a/tools/swift-remoteast-test/CMakeLists.txt b/tools/swift-remoteast-test/CMakeLists.txt
index 9fe95fc..4ab8f9c 100644
--- a/tools/swift-remoteast-test/CMakeLists.txt
+++ b/tools/swift-remoteast-test/CMakeLists.txt
@@ -1,8 +1,10 @@
-add_swift_executable(swift-remoteast-test
+add_swift_host_tool(swift-remoteast-test
   swift-remoteast-test.cpp
   LINK_LIBRARIES
     swiftFrontendTool
-    swiftRemoteAST)
+    swiftRemoteAST
+  SWIFT_COMPONENT tools
+)
 
 target_link_libraries(swift-remoteast-test edit)
 
diff --git a/utils/resolve-crashes.py b/utils/resolve-crashes.py
index 1091ee8..5935e3d 100755
--- a/utils/resolve-crashes.py
+++ b/utils/resolve-crashes.py
@@ -16,7 +16,7 @@
 # The regular expression we use to match compiler-crasher lines.
 regex = re.compile(
     '.*Swift(.*) :: '
-    '(compiler_crashers|compiler_crashers_2|IDE/crashers)/(.*\.swift).*')
+    '(compiler_crashers|compiler_crashers_2|IDE/crashers|SIL/crashers)/(.*\.swift|.*\.sil).*')
 
 # Take the output of lit as standard input.
 for line in sys.stdin:
diff --git a/validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil b/validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil
deleted file mode 100644
index 1f6eaa6..0000000
--- a/validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-sil-opt %s
-// REQUIRES: asserts
-sil@__:$<__ where τ:k>()->(
diff --git a/validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil b/validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil
deleted file mode 100644
index bed95c5..0000000
--- a/validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-sil-opt %s
-// REQUIRES: asserts
-protocol P{var e:<T>()->(
diff --git a/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil b/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil
deleted file mode 100644
index ab7468a..0000000
--- a/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-sil-opt %s
-// REQUIRES: asserts
-protocol l{func t-> <T>()->(
\ No newline at end of file
diff --git a/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil b/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil
deleted file mode 100644
index 5592b42..0000000
--- a/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-sil-opt %s
-// REQUIRES: asserts
-sil_global@d:$(<τ>()->(
\ No newline at end of file
diff --git a/validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil b/validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil
new file mode 100644
index 0000000..80c766e
--- /dev/null
+++ b/validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil
@@ -0,0 +1,3 @@
+// RUN: not %target-sil-opt %s
+// REQUIRES: asserts
+sil@__:$<__ where τ:k>()->(
diff --git a/validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil b/validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil
new file mode 100644
index 0000000..a04f138
--- /dev/null
+++ b/validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil
@@ -0,0 +1,3 @@
+// RUN: not %target-sil-opt %s
+// REQUIRES: asserts
+protocol P{var e:<T>()->(
diff --git a/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil b/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil
new file mode 100644
index 0000000..16aa0fb
--- /dev/null
+++ b/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil
@@ -0,0 +1,3 @@
+// RUN: not %target-sil-opt %s
+// REQUIRES: asserts
+protocol l{func t-> <T>()->(
diff --git a/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil b/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil
new file mode 100644
index 0000000..e9af348
--- /dev/null
+++ b/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil
@@ -0,0 +1,3 @@
+// RUN: not %target-sil-opt %s
+// REQUIRES: asserts
+sil_global@d:$(<τ>()->(
diff --git a/validation-test/compiler_crashers/28369-swift-decl-walk.swift b/validation-test/compiler_crashers/28369-swift-decl-walk.swift
index 59d40a4..10fbf9f 100644
--- a/validation-test/compiler_crashers/28369-swift-decl-walk.swift
+++ b/validation-test/compiler_crashers/28369-swift-decl-walk.swift
@@ -8,6 +8,7 @@
 // Credits: https://twitter.com/kiliankoe/status/752090953977036800
 
 // RUN: not --crash %target-swift-frontend %s -parse
+// XFAIL: *
 protocol P {
 }
 struct A<T> {