Merge pull request #12496 from davezarzycki/nfc_ExtInfo_withAPI_warn_unused_result

[AST] NFC: Warn if ExtInfo "with*" API results are unused
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index a78f8c7..d221583 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -89,8 +89,7 @@
   class PotentialArchetype;
 
   using UnresolvedType = llvm::PointerUnion<PotentialArchetype *, Type>;
-  struct ResolvedType;
-  class ResolveResult;
+  class ResolvedType;
 
   using RequirementRHS =
       llvm::PointerUnion3<Type, PotentialArchetype *, LayoutConstraint>;
@@ -215,9 +214,9 @@
     ///
     /// \returns true if this conformance is new to the equivalence class,
     /// and false otherwise.
-    bool recordConformanceConstraint(PotentialArchetype *pa,
+    bool recordConformanceConstraint(ResolvedType type,
                                      ProtocolDecl *proto,
-                                     const RequirementSource *source);
+                                     FloatingRequirementSource source);
 
     /// Find a source of the same-type constraint that maps a potential
     /// archetype in this equivalence class to a concrete type along with
@@ -342,32 +341,30 @@
                                    EquivalenceClass *unresolvedEquivClass,
                                    UnresolvedHandlingKind unresolvedHandling);
 
-  /// Resolve the conformance of the given potential archetype to
-  /// the given protocol when the potential archetype is known to be equivalent
-  /// to a concrete type.
+  /// Resolve the conformance of the given type to the given protocol when the
+  /// potential archetype is known to be equivalent to a concrete type.
   ///
   /// \returns the requirement source for the resolved conformance, or nullptr
   /// if the conformance could not be resolved.
-  const RequirementSource *resolveConcreteConformance(PotentialArchetype *pa,
+  const RequirementSource *resolveConcreteConformance(ResolvedType type,
                                                       ProtocolDecl *proto);
 
   /// Retrieve the constraint source conformance for the superclass constraint
   /// of the given potential archetype (if present) to the given protocol.
   ///
-  /// \param pa The potential archetype whose superclass constraint is being
-  /// queried.
+  /// \param type The type whose superclass constraint is being queried.
   ///
   /// \param proto The protocol to which we are establishing conformance.
-  const RequirementSource *resolveSuperConformance(PotentialArchetype *pa,
+  const RequirementSource *resolveSuperConformance(ResolvedType type,
                                                    ProtocolDecl *proto);
 
-  /// \brief Add a new conformance requirement specifying that the given
-  /// potential archetype conforms to the given protocol.
-  ConstraintResult addConformanceRequirement(PotentialArchetype *T,
-                                             ProtocolDecl *Proto,
-                                             const RequirementSource *Source);
-
 public:
+  /// \brief Add a new conformance requirement specifying that the given
+  /// type conforms to the given protocol.
+  ConstraintResult addConformanceRequirement(ResolvedType type,
+                                             ProtocolDecl *proto,
+                                             FloatingRequirementSource source);
+
   /// "Expand" the conformance of the given \c pa to the protocol \c proto,
   /// adding the requirements from its requirement signature, rooted at
   /// the given requirement \c source.
@@ -414,17 +411,20 @@
   /// Update the superclass for the equivalence class of \c T.
   ///
   /// This assumes that the constraint has already been recorded.
-  void updateSuperclass(PotentialArchetype *T,
+  ///
+  /// \returns true if anything in the equivalence class changed, false
+  /// otherwise.
+  bool updateSuperclass(ResolvedType type,
                         Type superclass,
-                        const RequirementSource *source);
+                        FloatingRequirementSource source);
 
 private:
   /// \brief Add a new superclass requirement specifying that the given
   /// potential archetype has the given type as an ancestor.
   ConstraintResult addSuperclassRequirementDirect(
-                                              PotentialArchetype *T,
-                                              Type Superclass,
-                                              const RequirementSource *Source);
+                                              ResolvedType type,
+                                              Type superclass,
+                                              FloatingRequirementSource source);
 
   /// \brief Add a new type requirement specifying that the given
   /// type conforms-to or is a superclass of the second type.
@@ -466,9 +466,9 @@
   ///
   /// \returns true if this requirement makes the set of requirements
   /// inconsistent, in which case a diagnostic will have been issued.
-  ConstraintResult addLayoutRequirementDirect(PotentialArchetype *PAT,
-                                              LayoutConstraint Layout,
-                                              const RequirementSource *Source);
+  ConstraintResult addLayoutRequirementDirect(ResolvedType type,
+                                              LayoutConstraint layout,
+                                              FloatingRequirementSource source);
 
   /// Add a new layout requirement to the subject.
   ConstraintResult addLayoutRequirement(
@@ -488,10 +488,6 @@
                                 const RequirementSource *parentSource,
                                 ModuleDecl *inferForModule);
 
-  /// Visit all of the potential archetypes.
-  template<typename F>
-  void visitPotentialArchetypes(F f);
-
 public:
   /// Construct a new generic signature builder.
   explicit GenericSignatureBuilder(ASTContext &ctx);
@@ -750,25 +746,19 @@
                             PotentialArchetype *pa);
 
 public:
-  /// \brief Resolve the given type to the potential archetype it names.
+  /// \brief Try to resolve the equivalence class of the given type.
   ///
-  /// The \c resolutionKind parameter describes how resolution should be
-  /// performed. If the potential archetype named by the given dependent type
-  /// already exists, it will be always returned. If it doesn't exist yet,
-  /// the \c resolutionKind dictates whether the potential archetype will
-  /// be created or whether null will be returned.
+  /// \param type The type to resolve.
   ///
-  /// For any type that cannot refer to an archetype, this routine returns the
-  /// equivalence class that would have to change to make the potential
-  /// archetype resolvable.
-  llvm::PointerUnion<PotentialArchetype *, EquivalenceClass *>
-  resolvePotentialArchetype(Type type,
-                            ArchetypeResolutionKind resolutionKind);
-
-  /// \brief Try to resolvew the equivalence class of the given type.
-  ResolveResult maybeResolveEquivalenceClass(
+  /// \param resolutionKind How to perform the resolution.
+  ///
+  /// \param wantExactPotentialArchetype Whether to return the precise
+  /// potential archetype described by the type (vs. just the equivalance
+  /// class and resolved type).
+  ResolvedType maybeResolveEquivalenceClass(
                                       Type type,
-                                      ArchetypeResolutionKind resolutionKind);
+                                      ArchetypeResolutionKind resolutionKind,
+                                      bool wantExactPotentialArchetype);
 
   /// \brief Resolve the equivalence class for the given type parameter,
   /// which provides information about that type.
@@ -792,7 +782,7 @@
   /// If the type cannot be resolved, e.g., because it is "too" recursive
   /// given the source, returns an unresolved result containing the equivalence
   /// class that would need to change to resolve this type.
-  ResolveResult resolve(UnresolvedType type, FloatingRequirementSource source);
+  ResolvedType resolve(UnresolvedType type, FloatingRequirementSource source);
 
   /// \brief Dump all of the requirements, both specified and inferred.
   LLVM_ATTRIBUTE_DEPRECATED(
@@ -1605,13 +1595,6 @@
     return identifier.assocTypeOrConcrete;
   }
 
-  /// Add a conformance to this potential archetype.
-  ///
-  /// \returns true if the conformance was new, false if it already existed.
-  bool addConformance(ProtocolDecl *proto,
-                      const RequirementSource *source,
-                      GenericSignatureBuilder &builder);
-
   /// Retrieve the set of nested types.
   const llvm::MapVector<Identifier, StoredNestedType> &getNestedTypes() const {
     return NestedTypes;
@@ -1668,15 +1651,6 @@
     return { };
   }
 
-  /// \brief Retrieve (or create) a nested type with the given name.
-  PotentialArchetype *getNestedType(Identifier Name,
-                                    ArchetypeResolutionKind kind,
-                                    GenericSignatureBuilder &builder);
-
-  /// \brief Retrieve (or create) a nested type with a known type.
-  PotentialArchetype *getNestedType(TypeDecl *type,
-                                    GenericSignatureBuilder &builder);
-
   /// \brief Retrieve (or create) a nested type that is the current best
   /// nested archetype anchor (locally) with the given name.
   ///
@@ -1697,17 +1671,6 @@
                         TypeDecl *type,
                         ArchetypeResolutionKind kind);
 
-  /// Update the named nested type when we know this type conforms to the given
-  /// protocol.
-  ///
-  /// \returns the potential archetype associated with either an associated
-  /// type or typealias of the given protocol, unless the \c kind implies that
-  /// a potential archetype should not be created if it's missing.
-  PotentialArchetype *updateNestedTypeForConformance(
-                        Identifier name,
-                        ProtocolDecl *protocol,
-                        ArchetypeResolutionKind kind);
-
   /// Retrieve the dependent type that describes this potential
   /// archetype.
   ///
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 124ade0..8aefea5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1684,6 +1684,11 @@
     return known->second;
   }
 
+  // While we are computing overridden declarations, pretend there are none.
+  auto mutableThis = const_cast<AssociatedTypeDecl *>(this);
+  mutableThis->AssociatedTypeDeclBits.ComputedOverridden = true;
+  mutableThis->AssociatedTypeDeclBits.HasOverridden = false;
+
   // Find associated types with the given name in all of the inherited
   // protocols.
   SmallVector<AssociatedTypeDecl *, 4> inheritedAssociatedTypes;
@@ -1718,8 +1723,8 @@
                        inheritedAssociatedTypes.end(),
                        compareSimilarAssociatedTypes);
 
-  return const_cast<AssociatedTypeDecl *>(this)
-    ->setOverriddenDecls(inheritedAssociatedTypes);
+  mutableThis->AssociatedTypeDeclBits.ComputedOverridden = false;
+  return mutableThis->setOverriddenDecls(inheritedAssociatedTypes);
 }
 
 ArrayRef<AssociatedTypeDecl *> AssociatedTypeDecl::setOverriddenDecls(
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 9e4a90b..c019755 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3000,6 +3000,8 @@
   // We shouldn't need this, but it shows up in recursive invocations.
   if (!isRequirementSignatureComputed()) {
     SmallPtrSet<ProtocolDecl *, 4> known;
+    if (auto resolver = getASTContext().getLazyResolver())
+      resolver->resolveInheritanceClause(const_cast<ProtocolDecl *>(this));
     for (auto inherited : getInherited()) {
       if (auto type = inherited.getType()) {
         // Only protocols can appear in the inheritance clause
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 5dbd75f..4d17832 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -1002,8 +1002,8 @@
   // Canonicalize the root type.
   auto source = getBestRequirementSource(conforms->second);
   auto subjectPA = source->getRootPotentialArchetype();
-  subjectPA = subjectPA->getArchetypeAnchor(*subjectPA->getBuilder());
-  Type rootType = subjectPA->getDependentType(getGenericParams());
+  Type rootType =
+    subjectPA->getOrCreateEquivalenceClass()->getAnchor(getGenericParams());
 
   // Build the path.
   buildPath(getRequirements(), source, protocol, rootType, nullptr);
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index cf19ba5..e2c6bde 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -61,7 +61,6 @@
   typedef EquivalenceClass::DerivedSameTypeComponent DerivedSameTypeComponent;
   typedef GenericSignatureBuilder::DelayedRequirement DelayedRequirement;
   typedef GenericSignatureBuilder::ResolvedType ResolvedType;
-  typedef GenericSignatureBuilder::ResolveResult ResolveResult;
 } // end anonymous namespace
 
 namespace llvm {
@@ -79,7 +78,11 @@
 STATISTIC(NumConcreteTypeConstraints,
           "# of same-type-to-concrete constraints tracked");
 STATISTIC(NumSuperclassConstraints, "# of superclass constraints tracked");
+STATISTIC(NumSuperclassConstraintsExtra,
+          "# of superclass constraints that add no information");
 STATISTIC(NumLayoutConstraints, "# of layout constraints tracked");
+STATISTIC(NumLayoutConstraintsExtra,
+          "# of layout constraints  that add no information");
 STATISTIC(NumSelfDerived, "# of self-derived constraints removed");
 STATISTIC(NumArchetypeAnchorCacheHits,
           "# of hits in the archetype anchor cache");
@@ -1558,22 +1561,119 @@
   }
 }
 
+class GenericSignatureBuilder::ResolvedType {
+  llvm::PointerUnion<PotentialArchetype *, Type> type;
+  EquivalenceClass *equivClass;
+
+  /// For a type that could not be resolved further unless the given
+  /// equivalence class changes.
+  ResolvedType(EquivalenceClass *equivClass)
+    : type(), equivClass(equivClass) { }
+
+public:
+  /// A specific resolved potential archetype.
+  ResolvedType(PotentialArchetype *pa)
+    : type(pa), equivClass(pa->getEquivalenceClassIfPresent()) { }
+
+  /// A resolved type within the given equivalence class.
+  ResolvedType(Type type, EquivalenceClass *equivClass)
+      : type(type), equivClass(equivClass) {
+    assert(type->isTypeParameter() == static_cast<bool>(equivClass) &&
+           "type parameters must have equivalence classes");
+  }
+
+  /// Return an unresolved result, which could be resolved when we
+  /// learn more information about the given equivalence class.
+  static ResolvedType forUnresolved(EquivalenceClass *equivClass) {
+    return ResolvedType(equivClass);
+  }
+
+  /// Return a result for a concrete type.
+  static ResolvedType forConcrete(Type concreteType) {
+    return ResolvedType(concreteType, nullptr);
+  }
+
+  /// Determine whether this result was resolved.
+  explicit operator bool() const { return !type.isNull(); }
+
+  /// Retrieve the dependent type.
+  Type getDependentType() const;
+
+  /// Retrieve the concrete type, or a null type if this result doesn't store
+  /// a concrete type.
+  Type getAsConcreteType() const {
+    assert(*this && "Doesn't contain any result");
+    if (equivClass) return Type();
+    return type.dyn_cast<Type>();
+  }
+
+  /// Realize a potential archetype for this type parameter.
+  PotentialArchetype *realizePotentialArchetype(
+                                            GenericSignatureBuilder &builder);
+
+  /// Retrieve the potential archetype, if already known.
+  PotentialArchetype *getPotentialArchetypeIfKnown() const {
+    return type.dyn_cast<PotentialArchetype *>();
+  }
+
+  /// Retrieve the equivalence class into which a resolved type refers.
+  EquivalenceClass *getEquivalenceClass() const {
+    assert(*this && "Only for resolved types");
+    if (equivClass) return equivClass;
+
+    // Create the equivalence class now.
+    return type.get<PotentialArchetype *>()->getOrCreateEquivalenceClass();
+  }
+
+  /// Retrieve the unresolved result.
+  EquivalenceClass *getUnresolvedEquivClass() const {
+    assert(!*this);
+    return equivClass;
+  }
+
+  /// Return an unresolved type.
+  ///
+  /// This loses equivalence-class information that could be useful, which
+  /// is unfortunate.
+  UnresolvedType getUnresolvedType() const {
+    return type;
+  }
+};
+
 bool EquivalenceClass::recordConformanceConstraint(
-                                 PotentialArchetype *pa,
+                                 ResolvedType type,
                                  ProtocolDecl *proto,
-                                 const RequirementSource *source) {
+                                 FloatingRequirementSource source) {
+  auto &builder = *members.front()->getBuilder();
+
   // If we haven't seen a conformance to this protocol yet, add it.
   bool inserted = false;
   auto known = conformsTo.find(proto);
   if (known == conformsTo.end()) {
     known = conformsTo.insert({ proto, { }}).first;
     inserted = true;
-    modified(*pa->getBuilder());
+    modified(builder);
     ++NumConformances;
+
+    // If there is a concrete type that resolves this conformance requirement,
+    // record the conformance.
+    if (!builder.resolveConcreteConformance(type, proto)) {
+      // Otherwise, determine whether there is a superclass constraint where the
+      // superclass conforms to this protocol.
+      (void)builder.resolveSuperConformance(type, proto);
+    }
+
+    // Resolve any associated type members.
+    for (auto assocType : proto->getAssociatedTypeMembers()) {
+      type.realizePotentialArchetype(builder)->updateNestedTypeForConformance(
+                                        assocType,
+                                        ArchetypeResolutionKind::AlreadyKnown);
+    }
   }
 
   // Record this conformance source.
-  known->second.push_back({pa, proto, source});
+  auto pa = type.realizePotentialArchetype(builder);
+  known->second.push_back({pa, proto, source.getSource(pa)});
   ++NumConformanceConstraints;
 
   return inserted;
@@ -2113,25 +2213,24 @@
 }
 
 const RequirementSource *
-GenericSignatureBuilder::resolveConcreteConformance(PotentialArchetype *pa,
+GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type,
                                                     ProtocolDecl *proto) {
-  auto equivClass = pa->getEquivalenceClassIfPresent();
-  auto concrete = equivClass ? equivClass->concreteType : Type();
+  auto equivClass = type.getEquivalenceClass();
+  auto concrete = equivClass->concreteType;
   if (!concrete) return nullptr;
 
   // Conformance to this protocol is redundant; update the requirement source
   // appropriately.
-  auto paEquivClass = pa->getOrCreateEquivalenceClass();
   const RequirementSource *concreteSource;
   if (auto writtenSource =
-        paEquivClass->findAnyConcreteConstraintAsWritten(pa))
+        equivClass->findAnyConcreteConstraintAsWritten(nullptr))
     concreteSource = writtenSource->source;
   else
-    concreteSource = paEquivClass->concreteTypeConstraints.front().source;
+    concreteSource = equivClass->concreteTypeConstraints.front().source;
 
   // Lookup the conformance of the concrete type to this protocol.
   auto conformance =
-      lookupConformance(pa->getDependentType({ })->getCanonicalType(),
+      lookupConformance(type.getDependentType()->getCanonicalType(),
                         concrete,
                         proto->getDeclaredInterfaceType()
                           ->castTo<ProtocolType>());
@@ -2145,27 +2244,26 @@
     }
 
     Impl->HadAnyError = true;
-    paEquivClass->invalidConcreteType = true;
+    equivClass->invalidConcreteType = true;
     return nullptr;
   }
 
   concreteSource = concreteSource->viaConcrete(*this, *conformance);
-  paEquivClass->recordConformanceConstraint(pa, proto, concreteSource);
+  equivClass->recordConformanceConstraint(type, proto, concreteSource);
   addConditionalRequirements(*this, *conformance);
   return concreteSource;
 }
-
 const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
-                                                        PotentialArchetype *pa,
+                                                        ResolvedType type,
                                                         ProtocolDecl *proto) {
   // Get the superclass constraint.
-  auto equivClass = pa->getEquivalenceClassIfPresent();
-  Type superclass = equivClass ? equivClass->superclass : nullptr;
+  auto equivClass = type.getEquivalenceClass();
+  Type superclass = equivClass->superclass;
   if (!superclass) return nullptr;
 
   // Lookup the conformance of the superclass to this protocol.
   auto conformance =
-    lookupConformance(pa->getDependentType({ })->getCanonicalType(),
+    lookupConformance(type.getDependentType()->getCanonicalType(),
                       superclass,
                       proto->getDeclaredInterfaceType()
                         ->castTo<ProtocolType>());
@@ -2173,144 +2271,67 @@
 
   // Conformance to this protocol is redundant; update the requirement source
   // appropriately.
-  auto paEquivClass = pa->getOrCreateEquivalenceClass();
   const RequirementSource *superclassSource;
   if (auto writtenSource =
-        paEquivClass->findAnySuperclassConstraintAsWritten(pa))
+        equivClass->findAnySuperclassConstraintAsWritten(nullptr))
     superclassSource = writtenSource->source;
   else
-    superclassSource = paEquivClass->superclassConstraints.front().source;
+    superclassSource = equivClass->superclassConstraints.front().source;
 
   superclassSource =
     superclassSource->viaSuperclass(*this, *conformance);
-  paEquivClass->recordConformanceConstraint(pa, proto, superclassSource);
+  equivClass->recordConformanceConstraint(type, proto, superclassSource);
   addConditionalRequirements(*this, *conformance);
   return superclassSource;
 }
 
-struct GenericSignatureBuilder::ResolvedType {
-  llvm::PointerUnion<PotentialArchetype *, Type> paOrT;
-
-  explicit ResolvedType(PotentialArchetype *pa) : paOrT(pa) {}
-  explicit ResolvedType(Type ty) : paOrT(ty) {}
-
-public:
-  static ResolvedType forConcreteType(Type t) {
-    assert(!t->isTypeParameter() &&
-           "concrete type with parameter should've been resolved");
-    return ResolvedType(t);
-  }
-
-  static ResolvedType forPotentialArchetype(PotentialArchetype *pa) {
-    return ResolvedType(pa);
-  }
-
-  Type getType() const { return paOrT.dyn_cast<Type>(); }
-  PotentialArchetype *getPotentialArchetype() const {
-    return paOrT.dyn_cast<PotentialArchetype *>();
-  }
-
-  bool isType() const { return paOrT.is<Type>(); }
-};
-
-class GenericSignatureBuilder::ResolveResult {
-  llvm::PointerUnion<Type, PotentialArchetype *> type;
-  EquivalenceClass *equivClass;
-
-  /// For a type that could not be resolved further unless the given
-  /// equivalence class changes.
-  ResolveResult(EquivalenceClass *equivClass)
-    : type(), equivClass(equivClass) { }
-
-public:
-  /// A specific resolved potential archetype.
-  ResolveResult(PotentialArchetype *pa)
-    : type(pa), equivClass(pa->getEquivalenceClassIfPresent()) { }
-
-  /// A resolved type within the given equivalence class.
-  ResolveResult(Type type, EquivalenceClass *equivClass)
-      : type(type), equivClass(equivClass) {
-    assert(type->isTypeParameter() == static_cast<bool>(equivClass) &&
-           "type parameters must have equivalence classes");
-  }
-
-  /// Return an unresolved result, which could be resolved when we
-  /// learn more information about the given equivalence class.
-  static ResolveResult forUnresolved(EquivalenceClass *equivClass){
-    return ResolveResult(equivClass);
-  }
-
-  /// Determine whether this result was resolved.
-  explicit operator bool() const { return !type.isNull(); }
-
-  /// Retrieve the resolved type.
-  ResolvedType getResolvedType(GenericSignatureBuilder &builder) const;
-
-  /// Retrieve the dependent type.
-  Type getDependentType() const;
-
-  /// Retrieve the potential archetype, if already known.
-  PotentialArchetype *getAsPotentialArchetype() const {
-    return type.dyn_cast<PotentialArchetype *>();
-  }
-
-  /// Retrieve the equivalence class into which a resolved type refers.
-  EquivalenceClass *getEquivalenceClass() const {
-    assert(*this && "Only for resolved types");
-    if (equivClass) return equivClass;
-
-    // Create the equivalence class now.
-    return type.get<PotentialArchetype *>()->getOrCreateEquivalenceClass();
-  }
-
-  /// Retrieve the unresolved result.
-  EquivalenceClass *getUnresolvedEquivClass() const {
-    assert(!*this);
-    return equivClass;
-  }
-};
-
-ResolvedType ResolveResult::getResolvedType(
-                                     GenericSignatureBuilder &builder) const {
-  assert(*this && "Unresolved result");
-
-  // Already-resolved potential archetype.
-  if (auto pa = type.dyn_cast<PotentialArchetype *>())
-    return ResolvedType::forPotentialArchetype(pa);
-
-  Type type = this->type.get<Type>();
-
-  // Concrete type.
-  if (!type->isTypeParameter())
-    return ResolvedType::forConcreteType(type);
+/// Realize a potential archetype for this type parameter.
+PotentialArchetype *ResolvedType::realizePotentialArchetype(
+                                           GenericSignatureBuilder &builder) {
+  if (auto pa = getPotentialArchetypeIfKnown())
+    return pa;
 
   // Resolve the potential archetype now.
+  Type type = this->type.get<Type>();
+  assert(type->isTypeParameter());
   auto pa =
-    builder.resolvePotentialArchetype(type,
-                                      ArchetypeResolutionKind::WellFormed)
-      .get<PotentialArchetype *>();
+    builder.maybeResolveEquivalenceClass(type,
+                                         ArchetypeResolutionKind::WellFormed,
+                                         /*wantExactPotentialArchetype=*/true)
+      .getPotentialArchetypeIfKnown();
   assert(pa && "Not a resolvable type!");
-  return ResolvedType::forPotentialArchetype(pa);
+
+  // Cache the potential archetype, now that it's been realized.
+  this->type = pa;
+  return pa;
 }
 
-Type ResolveResult::getDependentType() const {
+Type ResolvedType::getDependentType() const {
   // Already-resolved potential archetype.
   if (auto pa = type.dyn_cast<PotentialArchetype *>())
     return pa->getDependentType({ });
 
-  return type.get<Type>();
+  Type result = type.get<Type>();
+  return result->isTypeParameter() ? result : Type();
 }
 
 /// If there is a same-type requirement to be added for the given nested type
 /// due to a superclass constraint on the parent type, add it now.
 static void maybeAddSameTypeRequirementForNestedType(
-              GenericSignatureBuilder::PotentialArchetype *nestedPA,
-              const RequirementSource *superSource,
-              GenericSignatureBuilder &builder) {
+                                          ResolvedType nested,
+                                          const RequirementSource *superSource,
+                                          GenericSignatureBuilder &builder) {
   // If there's no super conformance, we're done.
   if (!superSource) return;
 
-  auto assocType = nestedPA->getResolvedAssociatedType();
+  // If the nested type is already concrete, we're done.
+  if (nested.getAsConcreteType()) return;
+
+  // Dig out the associated type.
+  AssociatedTypeDecl *assocType = nullptr;
+  if (auto depMemTy = nested.getDependentType()->getAs<DependentMemberType>())
+    assocType = depMemTy->getAssocType();
+
   if (!assocType) return;
 
   // Dig out the type witness.
@@ -2326,36 +2347,13 @@
   // Add the same-type constraint.
   auto nestedSource = superSource->viaParent(builder, assocType);
 
-  builder.addSameTypeRequirement(nestedPA, concreteType, nestedSource,
+  builder.addSameTypeRequirement(
+        nested.getUnresolvedType(), concreteType, nestedSource,
         GenericSignatureBuilder::UnresolvedHandlingKind::GenerateConstraints);
 }
 
-bool PotentialArchetype::addConformance(ProtocolDecl *proto,
-                                        const RequirementSource *source,
-                                        GenericSignatureBuilder &builder) {
-  // Check whether we already knew about this conformance.
-  auto equivClass = getOrCreateEquivalenceClass();
-  if (!equivClass->recordConformanceConstraint(this, proto, source))
-    return false;
-
-  // If there is a concrete type that resolves this conformance requirement,
-  // record the conformance.
-  if (!builder.resolveConcreteConformance(this, proto)) {
-    // Otherwise, determine whether there is a superclass constraint where the
-    // superclass conforms to this protocol.
-    (void)builder.resolveSuperConformance(this, proto);
-  }
-
-  // Resolve any existing nested types that need it.
-  for (auto &nested : NestedTypes) {
-    (void)updateNestedTypeForConformance(nested.first, proto,
-                                         ArchetypeResolutionKind::AlreadyKnown);
-  }
-
-  return true;
-}
-
-auto PotentialArchetype::getOrCreateEquivalenceClass() const -> EquivalenceClass * {
+auto PotentialArchetype::getOrCreateEquivalenceClass() const
+    -> EquivalenceClass * {
   // The equivalence class is stored on the representative.
   auto representative = getRepresentative();
   if (representative != this)
@@ -2572,7 +2570,7 @@
   // add it now; it was elided earlier.
   if (parentEquiv->conformsTo.count(proto) == 0) {
     auto source = parentEquiv->concreteTypeConstraints.front().source;
-    parent->addConformance(proto, source, builder);
+    parentEquiv->recordConformanceConstraint(parent, proto, source);
   }
 
   assert(parentEquiv->conformsTo.count(proto) > 0 &&
@@ -2608,27 +2606,6 @@
          SameTypeConflictCheckedLater());
 }
 
-PotentialArchetype *PotentialArchetype::getNestedType(
-                                           Identifier nestedName,
-                                           ArchetypeResolutionKind kind,
-                                           GenericSignatureBuilder &builder) {
-  // If we already have a nested type with this name, return it.
-  auto known = NestedTypes.find(nestedName);
-  if (known != NestedTypes.end())
-    return known->second.front();
-
-  // Retrieve the nested archetype anchor, which is the best choice (so far)
-  // for this nested type.
-  return getNestedArchetypeAnchor(nestedName, builder, kind);
-}
-
-PotentialArchetype *PotentialArchetype::getNestedType(
-                                            TypeDecl *type,
-                                            GenericSignatureBuilder &builder) {
-  return updateNestedTypeForConformance(type,
-                                        ArchetypeResolutionKind::WellFormed);
-}
-
 PotentialArchetype *PotentialArchetype::getNestedArchetypeAnchor(
                                            Identifier name,
                                            GenericSignatureBuilder &builder,
@@ -2655,19 +2632,6 @@
 
 
 PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
-                                                 Identifier name,
-                                                 ProtocolDecl *proto,
-                                                 ArchetypeResolutionKind kind) {
-  // Lookup the best type for this name.
-  auto bestType =
-    getOrCreateEquivalenceClass()->lookupNestedType(name, nullptr);
-  if (!bestType) return nullptr;
-
-  // Form the potential archetype.
-  return updateNestedTypeForConformance(bestType, kind);
-}
-
-PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
                                               TypeDecl *type,
                                               ArchetypeResolutionKind kind) {
   if (!type) return nullptr;
@@ -2797,11 +2761,8 @@
 
     // We know something concrete about the parent PA, so we need to propagate
     // that information to this new archetype.
-    // FIXME: This feels like massive overkill. Why do we have to loop?
     if (isConcreteType()) {
-      for (auto equivT : getRepresentative()->getEquivalenceClassMembers()) {
-        concretizeNestedTypeFromConcreteParent(equivT, resultPA, builder);
-      }
+      concretizeNestedTypeFromConcreteParent(this, resultPA, builder);
     }
   }
 
@@ -3026,128 +2987,6 @@
   return Context.getLazyResolver();
 }
 
-auto GenericSignatureBuilder::resolvePotentialArchetype(
-                                     Type type,
-                                     ArchetypeResolutionKind resolutionKind)
-  -> llvm::PointerUnion<PotentialArchetype *, EquivalenceClass *>
-{
-  if (auto genericParam = type->getAs<GenericTypeParamType>()) {
-    unsigned index = GenericParamKey(genericParam).findIndexIn(
-                                                           Impl->GenericParams);
-    if (index < Impl->GenericParams.size())
-      return Impl->PotentialArchetypes[index];
-
-    return (EquivalenceClass *)nullptr;
-  }
-
-  if (auto dependentMember = type->getAs<DependentMemberType>()) {
-    auto base = resolvePotentialArchetype(
-                  dependentMember->getBase(), resolutionKind);
-    auto basePA = base.dyn_cast<PotentialArchetype *>();
-    if (!basePA)
-      return base;
-
-    // If we know the associated type already, get that specific type.
-    PotentialArchetype *nestedPA;
-    if (auto assocType = dependentMember->getAssocType()) {
-      nestedPA =
-        basePA->updateNestedTypeForConformance(assocType, resolutionKind);
-    } else {
-      // Resolve based on name alone.
-      auto name = dependentMember->getName();
-      nestedPA = basePA->getNestedArchetypeAnchor(name, *this, resolutionKind);
-    }
-
-    // If we found a nested potential archetype, return it.
-    if (nestedPA)
-      return nestedPA;
-
-    // Otherwise, get/create an equivalence class for the base potential
-    // archetype.
-    return basePA->getOrCreateEquivalenceClass();
-  }
-
-  return (EquivalenceClass *)nullptr;
-}
-
-ResolveResult GenericSignatureBuilder::maybeResolveEquivalenceClass(
-                                    Type type,
-                                    ArchetypeResolutionKind resolutionKind) {
-  // The equivalence class of a generic type is known directly.
-  if (auto genericParam = type->getAs<GenericTypeParamType>()) {
-    unsigned index = GenericParamKey(genericParam).findIndexIn(
-                                                           Impl->GenericParams);
-    if (index < Impl->GenericParams.size()) {
-      auto pa = Impl->PotentialArchetypes[index];
-      return ResolveResult(type, pa->getOrCreateEquivalenceClass());
-    }
-
-    return ResolveResult::forUnresolved(nullptr);
-  }
-
-  // The equivalence class of a dependent member type is determined by its
-  // base equivalence class.
-  if (auto depMemTy = type->getAs<DependentMemberType>()) {
-    // Find the equivalence class of the base.
-    auto resolvedBase = maybeResolveEquivalenceClass(depMemTy->getBase(),
-                                                     resolutionKind);
-    if (!resolvedBase) return resolvedBase;
-
-    // Find the nested type declaration for this.
-    auto baseEquivClass = resolvedBase.getEquivalenceClass();
-    TypeDecl *nestedTypeDecl;
-    if (auto assocType = depMemTy->getAssocType()) {
-      nestedTypeDecl = assocType;
-    } else {
-      nestedTypeDecl = baseEquivClass->lookupNestedType(depMemTy->getName());
-      if (!nestedTypeDecl) {
-        return ResolveResult::forUnresolved(baseEquivClass);
-      }
-    }
-
-    // Retrieve the "smallest" type in the equivalence class, by depth, and
-    // use that to find a nested potential archetype. We used the smallest
-    // type by depth to limit expansion of the type graph.
-    auto basePA = baseEquivClass->members.front();
-    auto nestedPA =
-      basePA->updateNestedTypeForConformance(nestedTypeDecl, resolutionKind);
-    if (!nestedPA)
-      return ResolveResult::forUnresolved(baseEquivClass);
-
-    // If base resolved to the anchor, then the nested potential archetype
-    // we found is the resolved potential archetype. Return it directly,
-    // so it doesn't need to be resolved again.
-    if (basePA == resolvedBase.getAsPotentialArchetype())
-      return ResolveResult(nestedPA);
-
-    // Compute the resolved dependent type to return.
-    Type resolvedBaseType = resolvedBase.getDependentType();
-    Type resolvedMemberType;
-    if (auto assocType = dyn_cast<AssociatedTypeDecl>(nestedTypeDecl)) {
-      resolvedMemberType =
-        DependentMemberType::get(resolvedBaseType, assocType);
-    } else {
-      // Note: strange case that might not even really be dependent.
-      resolvedMemberType =
-        DependentMemberType::get(resolvedBaseType, depMemTy->getName());
-    }
-
-    return ResolveResult(resolvedMemberType,
-                         nestedPA->getOrCreateEquivalenceClass());
-  }
-
-  return ResolveResult::forUnresolved(nullptr);
-}
-
-EquivalenceClass *GenericSignatureBuilder::resolveEquivalenceClass(
-                                    Type type,
-                                    ArchetypeResolutionKind resolutionKind) {
-  if (auto resolved = maybeResolveEquivalenceClass(type, resolutionKind))
-    return resolved.getEquivalenceClass();
-
-  return nullptr;
-}
-
 /// Resolve any unresolved dependent member types using the given builder.
 static Type resolveDependentMemberTypes(GenericSignatureBuilder &builder,
                                         Type type,
@@ -3181,42 +3020,124 @@
     return None;
   });
 }
-auto GenericSignatureBuilder::resolve(UnresolvedType paOrT,
-                                      FloatingRequirementSource source)
-    -> ResolveResult {
-  auto pa = paOrT.dyn_cast<PotentialArchetype *>();
-  if (auto type = paOrT.dyn_cast<Type>()) {
-    // Determine what kind of resolution we want.
-    ArchetypeResolutionKind resolutionKind =
-      ArchetypeResolutionKind::WellFormed;
-    if (!source.isExplicit() && source.isRecursive(type, *this))
-      resolutionKind = ArchetypeResolutionKind::AlreadyKnown;
 
-    // If it's not a type parameter, it won't directly resolve to one.
-    if (!type->isTypeParameter()) {
-      // If there is a type parameter somewhere in this type, resolve it.
-      if (type->hasTypeParameter()) {
-        Type resolved =
-          resolveDependentMemberTypes(*this, type, resolutionKind);
-        if (resolved->hasError() && !type->hasError())
-          return ResolveResult::forUnresolved(nullptr);
-
-        type = resolved;
-      }
-
-      return ResolveResult(type, nullptr);
+ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass(
+                                    Type type,
+                                    ArchetypeResolutionKind resolutionKind,
+                                    bool wantExactPotentialArchetype) {
+  // The equivalence class of a generic type is known directly.
+  if (auto genericParam = type->getAs<GenericTypeParamType>()) {
+    unsigned index = GenericParamKey(genericParam).findIndexIn(
+                                                           Impl->GenericParams);
+    if (index < Impl->GenericParams.size()) {
+      return ResolvedType(Impl->PotentialArchetypes[index]);
     }
 
-    // Attempt to resolve the type parameter to a potential archetype. If this
-    // fails, it's because we weren't allowed to resolve anything now.
-    auto resolved = resolvePotentialArchetype(type, resolutionKind);
-    pa = resolved.dyn_cast<PotentialArchetype *>();
-    if (!pa) {
-      return ResolveResult::forUnresolved(resolved.get<EquivalenceClass *>());
-    }
+    return ResolvedType::forUnresolved(nullptr);
   }
 
-  return ResolveResult(pa);
+  // The equivalence class of a dependent member type is determined by its
+  // base equivalence class.
+  if (auto depMemTy = type->getAs<DependentMemberType>()) {
+    // Find the equivalence class of the base.
+    auto resolvedBase =
+      maybeResolveEquivalenceClass(depMemTy->getBase(),
+                                   resolutionKind,
+                                   wantExactPotentialArchetype);
+    if (!resolvedBase) return resolvedBase;
+
+    // Find the nested type declaration for this.
+    auto baseEquivClass = resolvedBase.getEquivalenceClass();
+    TypeDecl *nestedTypeDecl;
+    if (auto assocType = depMemTy->getAssocType()) {
+      nestedTypeDecl = assocType;
+    } else {
+      nestedTypeDecl = baseEquivClass->lookupNestedType(depMemTy->getName());
+      if (!nestedTypeDecl) {
+        return ResolvedType::forUnresolved(baseEquivClass);
+      }
+    }
+
+    // Retrieve the "smallest" type in the equivalence class, by depth, and
+    // use that to find a nested potential archetype. We used the smallest
+    // type by depth to limit expansion of the type graph.
+    PotentialArchetype *basePA;
+    if (wantExactPotentialArchetype) {
+      basePA = resolvedBase.getPotentialArchetypeIfKnown();
+      if (!basePA) return ResolvedType::forUnresolved(baseEquivClass);
+    } else {
+      basePA = baseEquivClass->members.front();
+    }
+
+    auto nestedPA =
+      basePA->updateNestedTypeForConformance(nestedTypeDecl, resolutionKind);
+    if (!nestedPA)
+      return ResolvedType::forUnresolved(baseEquivClass);
+
+    // If base resolved to the anchor, then the nested potential archetype
+    // we found is the resolved potential archetype. Return it directly,
+    // so it doesn't need to be resolved again.
+    if (basePA == resolvedBase.getPotentialArchetypeIfKnown())
+      return ResolvedType(nestedPA);
+
+    // Compute the resolved dependent type to return.
+    Type resolvedBaseType = resolvedBase.getDependentType();
+    Type resolvedMemberType;
+    if (auto assocType = dyn_cast<AssociatedTypeDecl>(nestedTypeDecl)) {
+      resolvedMemberType =
+        DependentMemberType::get(resolvedBaseType, assocType);
+    } else {
+      // Note: strange case that might not even really be dependent.
+      resolvedMemberType =
+        DependentMemberType::get(resolvedBaseType, depMemTy->getName());
+    }
+
+    return ResolvedType(resolvedMemberType,
+                         nestedPA->getOrCreateEquivalenceClass());
+  }
+
+  // If it's not a type parameter, it won't directly resolve to one.
+  // FIXME: Generic typealiases contradict the assumption above.
+  // If there is a type parameter somewhere in this type, resolve it.
+  if (type->hasTypeParameter()) {
+    Type resolved =
+    resolveDependentMemberTypes(*this, type,
+                                ArchetypeResolutionKind::WellFormed);
+    if (resolved->hasError() && !type->hasError())
+      return ResolvedType::forUnresolved(nullptr);
+
+    type = resolved;
+  }
+
+  return ResolvedType::forConcrete(type);
+}
+
+EquivalenceClass *GenericSignatureBuilder::resolveEquivalenceClass(
+                                    Type type,
+                                    ArchetypeResolutionKind resolutionKind) {
+  if (auto resolved =
+        maybeResolveEquivalenceClass(type, resolutionKind,
+                                     /*wantExactPotentialArchetype=*/false))
+    return resolved.getEquivalenceClass();
+
+  return nullptr;
+}
+
+auto GenericSignatureBuilder::resolve(UnresolvedType paOrT,
+                                      FloatingRequirementSource source)
+    -> ResolvedType {
+  if (auto pa = paOrT.dyn_cast<PotentialArchetype *>())
+    return ResolvedType(pa);
+
+  // Determine what kind of resolution we want.
+    Type type = paOrT.dyn_cast<Type>();
+  ArchetypeResolutionKind resolutionKind =
+    ArchetypeResolutionKind::WellFormed;
+  if (!source.isExplicit() && source.isRecursive(type, *this))
+    resolutionKind = ArchetypeResolutionKind::AlreadyKnown;
+
+  return maybeResolveEquivalenceClass(type, resolutionKind,
+                                      /*wantExactPotentialArchetype=*/true);
 }
 
 void GenericSignatureBuilder::addGenericParameter(GenericTypeParamDecl *GenericParam) {
@@ -3594,38 +3515,50 @@
 }
 
 ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
-                               PotentialArchetype *PAT,
-                               ProtocolDecl *Proto,
-                               const RequirementSource *Source) {
-  // Add the requirement, if we haven't done so already.
-  if (!PAT->addConformance(Proto, Source, *this))
+                               ResolvedType type,
+                               ProtocolDecl *proto,
+                               FloatingRequirementSource source) {
+  // Add the conformance requirement, bailing out earlier if we've already
+  // seen it.
+  auto equivClass = type.getEquivalenceClass();
+  if (!equivClass->recordConformanceConstraint(type, proto, source))
     return ConstraintResult::Resolved;
 
-  return expandConformanceRequirement(PAT, Proto, Source,
+  // FIXME: Resolve later.
+  auto pa = type.realizePotentialArchetype(*this);
+  return expandConformanceRequirement(pa, proto, source.getSource(pa),
                                       /*onlySameTypeRequirements=*/false);
 }
 
 ConstraintResult GenericSignatureBuilder::addLayoutRequirementDirect(
-                                             PotentialArchetype *PAT,
-                                             LayoutConstraint Layout,
-                                             const RequirementSource *Source) {
-  auto equivClass = PAT->getOrCreateEquivalenceClass();
-
-  // Record this layout constraint.
-  equivClass->layoutConstraints.push_back({PAT, Layout, Source});
-  equivClass->modified(*this);
-  ++NumLayoutConstraints;
+                                             ResolvedType type,
+                                             LayoutConstraint layout,
+                                             FloatingRequirementSource source) {
+  auto equivClass = type.getEquivalenceClass();
 
   // Update the layout in the equivalence class, if we didn't have one already.
-  if (!equivClass->layout)
-    equivClass->layout = Layout;
-  else {
+  bool anyChanges = false;
+  if (!equivClass->layout) {
+    equivClass->layout = layout;
+    anyChanges = true;
+  } else {
     // Try to merge layout constraints.
-    auto mergedLayout = equivClass->layout.merge(Layout);
-    if (mergedLayout->isKnownLayout() && mergedLayout != equivClass->layout)
+    auto mergedLayout = equivClass->layout.merge(layout);
+    if (mergedLayout->isKnownLayout() && mergedLayout != equivClass->layout) {
       equivClass->layout = mergedLayout;
+      anyChanges = true;
+    }
   }
 
+  // FIXME: Don't want to realize this potential archetype if we can avoid it.
+  auto pa = type.realizePotentialArchetype(*this);
+
+  // Record this layout constraint.
+  equivClass->layoutConstraints.push_back({pa, layout, source.getSource(pa)});
+  equivClass->modified(*this);
+  ++NumLayoutConstraints;
+  if (!anyChanges) ++NumLayoutConstraintsExtra;
+
   return ConstraintResult::Resolved;
 }
 
@@ -3635,28 +3568,25 @@
                                              FloatingRequirementSource source,
                                              UnresolvedHandlingKind unresolvedHandling) {
   // Resolve the subject.
-  auto maybeResolvedSubject = resolve(subject, source);
-  if (!maybeResolvedSubject) {
+  auto resolvedSubject = resolve(subject, source);
+  if (!resolvedSubject) {
     return handleUnresolvedRequirement(
                                RequirementKind::Layout, subject,
                                layout, source,
-                               maybeResolvedSubject.getUnresolvedEquivClass(),
+                               resolvedSubject.getUnresolvedEquivClass(),
                                unresolvedHandling);
   }
 
-  /// Resolve the subject fully.
-  ResolvedType resolvedSubject = maybeResolvedSubject.getResolvedType(*this);
-
   // If this layout constraint applies to a concrete type, we can fully
   // resolve it now.
-  if (resolvedSubject.isType()) {
+  if (auto concreteType = resolvedSubject.getAsConcreteType()) {
     // If a layout requirement was explicitly written on a concrete type,
     // complain.
     if (source.isExplicit() && source.getLoc().isValid()) {
       Impl->HadAnyError = true;
 
       Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
-                     TypeLoc::withoutLoc(resolvedSubject.getType()));
+                     TypeLoc::withoutLoc(concreteType));
       return ConstraintResult::Concrete;
     }
 
@@ -3666,32 +3596,36 @@
     return ConstraintResult::Resolved;
   }
 
-  auto pa = resolvedSubject.getPotentialArchetype();
-  return addLayoutRequirementDirect(pa, layout, source.getSource(pa));
+  return addLayoutRequirementDirect(resolvedSubject, layout, source);
 }
 
-void GenericSignatureBuilder::updateSuperclass(
-                                           PotentialArchetype *T,
+bool GenericSignatureBuilder::updateSuperclass(
+                                           ResolvedType type,
                                            Type superclass,
-                                           const RequirementSource *source) {
-  auto equivClass = T->getOrCreateEquivalenceClass();
+                                           FloatingRequirementSource source) {
+  auto equivClass = type.getEquivalenceClass();
 
   // Local function to handle the update of superclass conformances
   // when the superclass constraint changes.
   auto updateSuperclassConformances = [&] {
     for (const auto &conforms : equivClass->conformsTo) {
       auto proto = conforms.first;
-      if (auto superSource = resolveSuperConformance(T, proto)) {
+      if (auto superSource = resolveSuperConformance(type, proto)) {
         for (auto assocType : proto->getAssociatedTypeMembers()) {
+          // Only do this for the anchor.
+          if (assocType != assocType->getAssociatedTypeAnchor())
+            continue;
 
-          const auto &nestedTypes = T->getNestedTypes();
-          auto nested = nestedTypes.find(assocType->getName());
-          if (nested == nestedTypes.end()) continue;
-
-          for (auto nestedPA : nested->second) {
-            if (nestedPA->getResolvedAssociatedType() == assocType)
-              maybeAddSameTypeRequirementForNestedType(nestedPA, superSource,
-                                                       *this);
+          // FIXME: More efficient way to extend resolved type?
+          Type nestedType =
+            DependentMemberType::get(type.getDependentType(), assocType);
+          if (auto nested =
+                maybeResolveEquivalenceClass(
+                                 nestedType,
+                                 ArchetypeResolutionKind::AlreadyKnown,
+                                 /*wantExactPotentialArchetype=*/true)) {
+            maybeAddSameTypeRequirementForNestedType(nested, superSource,
+                                                     *this);
           }
         }
       }
@@ -3706,15 +3640,17 @@
 
     // Presence of a superclass constraint implies a _Class layout
     // constraint.
-    auto layoutReqSource = source->viaDerived(*this);
-    addLayoutRequirementDirect(T,
+    // FIXME: FloatingRequirementSource should be able to handle "viaDerived".
+    auto pa = type.realizePotentialArchetype(*this);
+    auto layoutReqSource = source.getSource(pa)->viaDerived(*this);
+    addLayoutRequirementDirect(type,
                          LayoutConstraint::getLayoutConstraint(
                              superclass->getClassOrBoundGenericClass()->isObjC()
                                  ? LayoutConstraintKind::Class
                                  : LayoutConstraintKind::NativeClass,
                              getASTContext()),
                          layoutReqSource);
-    return;
+    return true;
   }
 
   // T already has a superclass; make sure it's related.
@@ -3734,25 +3670,31 @@
 
     // We've strengthened the bound, so update superclass conformances.
     updateSuperclassConformances();
-    return;
+    return true;
   }
 
-  return;
+  return false;
 }
 
 ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
-                                            PotentialArchetype *T,
+                                            ResolvedType type,
                                             Type superclass,
-                                            const RequirementSource *source) {
+                                            FloatingRequirementSource source) {
+  // FIXME: realize much later.
+  auto T = type.realizePotentialArchetype(*this);
+  auto resolvedSource = source.getSource(T);
+
   // Record the constraint.
-  auto equivClass = T->getOrCreateEquivalenceClass();
+  auto equivClass = type.getEquivalenceClass();
   equivClass->superclassConstraints.push_back(
-                                    ConcreteConstraint{T, superclass, source});
+                          ConcreteConstraint{T, superclass, resolvedSource});
   equivClass->modified(*this);
   ++NumSuperclassConstraints;
 
   // Update the equivalence class with the constraint.
-  updateSuperclass(T, superclass, source);
+  if (!updateSuperclass(type, superclass, source))
+    ++NumSuperclassConstraintsExtra;
+
   return ConstraintResult::Resolved;
 }
 
@@ -3770,23 +3712,20 @@
     FloatingRequirementSource source, UnresolvedHandlingKind unresolvedHandling,
     ModuleDecl *inferForModule) {
   // Resolve the constraint.
-  auto maybeResolvedConstraint = resolve(constraint, source);
-  if (!maybeResolvedConstraint) {
+  auto resolvedConstraint = resolve(constraint, source);
+  if (!resolvedConstraint) {
     return handleUnresolvedRequirement(
                              RequirementKind::Conformance, subject,
                              toRequirementRHS(constraint), source,
-                             maybeResolvedConstraint.getUnresolvedEquivClass(),
+                             resolvedConstraint.getUnresolvedEquivClass(),
                              unresolvedHandling);
   }
 
   // The right-hand side needs to be concrete.
-  ResolvedType resolvedConstraint =
-    maybeResolvedConstraint.getResolvedType(*this);
-  Type constraintType;
-  if (auto constraintPA = resolvedConstraint.getPotentialArchetype()) {
-    constraintType = constraintPA->getDependentType(Impl->GenericParams);
-  } else {
-    constraintType = resolvedConstraint.getType();
+  Type constraintType = resolvedConstraint.getAsConcreteType();
+  if (!constraintType) {
+    constraintType = resolvedConstraint.getDependentType();
+    assert(constraintType && "No type to express resolved constraint?");
   }
 
   // Check whether we have a reasonable constraint type at all.
@@ -3808,8 +3747,8 @@
   }
 
   // Resolve the subject. If we can't, delay the constraint.
-  auto maybeResolvedSubject = resolve(subject, source);
-  if (!maybeResolvedSubject) {
+  auto resolvedSubject = resolve(subject, source);
+  if (!resolvedSubject) {
     auto recordedKind =
       constraintType->isExistentialType()
         ? RequirementKind::Conformance
@@ -3817,17 +3756,14 @@
     return handleUnresolvedRequirement(
                                recordedKind, subject, constraintType,
                                source,
-                               maybeResolvedSubject.getUnresolvedEquivClass(),
+                               resolvedSubject.getUnresolvedEquivClass(),
                                unresolvedHandling);
   }
 
   // If the resolved subject is a type, there may be things we can infer (if it
   // conditionally conforms to the protocol), and we can probably perform
   // diagnostics here.
-  ResolvedType resolvedSubject = maybeResolvedSubject.getResolvedType(*this);
-  if (resolvedSubject.isType()) {
-    auto subjectType = resolvedSubject.getType();
-
+  if (auto subjectType = resolvedSubject.getAsConcreteType()) {
     if (constraintType->isExistentialType()) {
       auto layout = constraintType->getExistentialLayout();
       for (auto *proto : layout.getProtocols()) {
@@ -3862,34 +3798,29 @@
     return ConstraintResult::Resolved;
   }
 
-  auto subjectPA = resolvedSubject.getPotentialArchetype();
-  assert(subjectPA && "No potential archetype?");
-
-  auto resolvedSource = source.getSource(subjectPA);
-
   // Protocol requirements.
   if (constraintType->isExistentialType()) {
     bool anyErrors = false;
     auto layout = constraintType->getExistentialLayout();
 
     if (auto layoutConstraint = layout.getLayoutConstraint()) {
-      if (isErrorResult(addLayoutRequirementDirect(subjectPA,
+      if (isErrorResult(addLayoutRequirementDirect(resolvedSubject,
                                                    layoutConstraint,
-                                                   resolvedSource)))
+                                                   source)))
         anyErrors = true;
     }
 
     if (layout.superclass) {
-      if (isErrorResult(addSuperclassRequirementDirect(subjectPA,
+      if (isErrorResult(addSuperclassRequirementDirect(resolvedSubject,
                                                        layout.superclass,
-                                                       resolvedSource)))
+                                                       source)))
         anyErrors = true;
     }
 
     for (auto *proto : layout.getProtocols()) {
       auto *protoDecl = proto->getDecl();
-      if (isErrorResult(addConformanceRequirement(subjectPA, protoDecl,
-                                                  resolvedSource)))
+      if (isErrorResult(addConformanceRequirement(resolvedSubject, protoDecl,
+                                                  source)))
         anyErrors = true;
     }
 
@@ -3898,8 +3829,8 @@
   }
 
   // Superclass constraint.
-  return addSuperclassRequirementDirect(subjectPA, constraintType,
-                                        resolvedSource);
+  return addSuperclassRequirementDirect(resolvedSubject, constraintType,
+                                        source);
 }
 
 void GenericSignatureBuilder::PotentialArchetype::addSameTypeConstraint(
@@ -3942,7 +3873,9 @@
   if (parentPA == parentRepPA) return;
 
   PotentialArchetype *existingPA =
-    parentRepPA->getNestedType(nestedPA->getResolvedType(), *this);
+    parentRepPA->updateNestedTypeForConformance(
+                                        nestedPA->getResolvedType(),
+                                        ArchetypeResolutionKind::WellFormed);
 
   auto sameNamedSource =
     FloatingRequirementSource::forNestedTypeNameMatch(
@@ -4052,7 +3985,8 @@
   // Add all of the protocol conformance requirements of T2 to T1.
   if (equivClass2) {
     for (const auto &entry : equivClass2->conformsTo) {
-      T1->addConformance(entry.first, entry.second.front().source, *this);
+      equivClass->recordConformanceConstraint(T1, entry.first,
+                                              entry.second.front().source);
 
       auto &constraints1 = equivClass->conformsTo[entry.first];
       // FIXME: Go through recordConformanceConstraint()?
@@ -4227,18 +4161,19 @@
                                        unresolvedHandling);
   }
 
-  return addSameTypeRequirementDirect(resolved1.getResolvedType(*this),
-                                      resolved2.getResolvedType(*this),
-                                      source, diagnoseMismatch);
+  return addSameTypeRequirementDirect(resolved1, resolved2, source,
+                                      diagnoseMismatch);
 }
 
 ConstraintResult GenericSignatureBuilder::addSameTypeRequirementDirect(
-    ResolvedType paOrT1, ResolvedType paOrT2, FloatingRequirementSource source,
+    ResolvedType paOrT1, ResolvedType paOrT2,
+    FloatingRequirementSource source,
     llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
-  auto pa1 = paOrT1.getPotentialArchetype();
-  auto pa2 = paOrT2.getPotentialArchetype();
-  auto t1 = paOrT1.getType();
-  auto t2 = paOrT2.getType();
+  auto t1 = paOrT1.getAsConcreteType();
+  auto *pa1 = t1 ? nullptr : paOrT1.realizePotentialArchetype(*this);
+
+  auto t2 = paOrT2.getAsConcreteType();
+  auto *pa2 = t2 ? nullptr : paOrT2.realizePotentialArchetype(*this);
 
   // If both sides of the requirement are type parameters, equate them.
   if (pa1 && pa2) {
@@ -4682,23 +4617,6 @@
   }
 }
 
-/// Retrieve the "local" archetype anchor for the given potential archetype,
-/// which rebuilds this potential archetype using the archetype anchors of
-/// the parent types.
-static PotentialArchetype *getLocalAnchor(PotentialArchetype *pa,
-                                          GenericSignatureBuilder &builder) {
-  auto parent = pa->getParent();
-  if (!parent) return pa;
-
-  auto parentAnchor = getLocalAnchor(parent, builder);
-  if (!parentAnchor) return pa;
-  auto localAnchor =
-    parentAnchor->getNestedArchetypeAnchor(
-                                pa->getNestedName(), builder,
-                                ArchetypeResolutionKind::CompleteWellFormed);
-  return localAnchor ? localAnchor : pa;
-}
-
 void
 GenericSignatureBuilder::finalize(SourceLoc loc,
                            ArrayRef<GenericTypeParamType *> genericParams,
@@ -4843,19 +4761,9 @@
   };
 
   // FIXME: Expand all conformance requirements. This is expensive :(
-  visitPotentialArchetypes([&](PotentialArchetype *archetype) {
-    if (archetype != archetype->getRepresentative()) return;
-
-    // Make sure that we've build the archetype anchors for each potential
-    // archetype in this equivalence class. This is important to do for *all*
-    // potential archetypes because some non-archetype anchors will nonetheless
-    // be used in the canonicalized requirements.
-    for (auto pa : archetype->getEquivalenceClassMembers())
-      (void)getLocalAnchor(pa, *this);
-
-    if (auto equivClass = archetype->getEquivalenceClassIfPresent())
-      expandSameTypeConstraints(*this, equivClass);
-  });
+  for (auto &equivClass : Impl->EquivalenceClasses) {
+      expandSameTypeConstraints(*this, &equivClass);
+  }
 
   // Check same-type constraints.
   for (const auto &equivClass : Impl->EquivalenceClasses) {
@@ -5666,8 +5574,9 @@
     if (auto pa =
             builder.maybeResolveEquivalenceClass(
                                      type,
-                                     ArchetypeResolutionKind::AlreadyKnown)
-              .getAsPotentialArchetype())
+                                     ArchetypeResolutionKind::AlreadyKnown,
+                                     /*wantExactPotentialArchetype=*/true)
+              .getPotentialArchetypeIfKnown())
       return getPotentialArchetypeVirtualComponent(pa);
 
     return getTypeVirtualComponent(type);
@@ -6185,49 +6094,6 @@
     diag::previous_layout_constraint);
 }
 
-template<typename F>
-void GenericSignatureBuilder::visitPotentialArchetypes(F f) {
-  // Stack containing all of the potential archetypes to visit.
-  SmallVector<PotentialArchetype *, 4> stack;
-  llvm::SmallPtrSet<PotentialArchetype *, 4> visited;
-
-  // Add top-level potential archetypes to the stack.
-  for (const auto pa : Impl->PotentialArchetypes) {
-    if (visited.insert(pa).second)
-      stack.push_back(pa);
-  }
-
-  // Visit all of the potential archetypes.
-  while (!stack.empty()) {
-    PotentialArchetype *pa = stack.back();
-    stack.pop_back();
-    f(pa);
-
-    // Visit the archetype anchor.
-    if (auto anchor = pa->getArchetypeAnchor(*this)) {
-      if (visited.insert(anchor).second) {
-        stack.push_back(anchor);
-      }
-    }
-
-    // Visit everything else in this equivalence class.
-    for (auto equivPA : pa->getEquivalenceClassMembers()) {
-      if (visited.insert(equivPA).second) {
-        stack.push_back(equivPA);
-      }
-    }
-
-    // Visit nested potential archetypes.
-    for (const auto &nested : pa->getNestedTypes()) {
-      for (auto nestedPA : nested.second) {
-        if (visited.insert(nestedPA).second) {
-          stack.push_back(nestedPA);
-        }
-      }
-    }
-  }
-}
-
 namespace {
   /// Retrieve the best requirement source from a set of constraints.
   template<typename T>
@@ -6253,9 +6119,16 @@
                            const RequirementSource *source)> f) {
   // Collect all archetypes.
   SmallVector<PotentialArchetype *, 8> archetypes;
-  visitPotentialArchetypes([&](PotentialArchetype *archetype) {
-    archetypes.push_back(archetype);
-  });
+  for (auto &equivClass : Impl->EquivalenceClasses) {
+    if (equivClass.derivedSameTypeComponents.empty()) {
+      checkSameTypeConstraints(Impl->GenericParams,
+                               equivClass.members.front()->getRepresentative());
+    }
+
+    for (const auto &component : equivClass.derivedSameTypeComponents) {
+      archetypes.push_back(component.anchor);
+    }
+  }
 
   // Sort the archetypes in canonical order.
   llvm::array_pod_sort(archetypes.begin(), archetypes.end(),
@@ -6267,15 +6140,7 @@
     //
     // FIXME: O(n) in the number of implied connected components within the
     // equivalence class. The equivalence class should be small, but...
-    auto rep = archetype->getRepresentative();
-    auto equivClass = rep->getOrCreateEquivalenceClass();
-
-    // If we didn't compute the derived same-type components yet, do so now.
-    if (equivClass->derivedSameTypeComponents.empty()) {
-      checkSameTypeConstraints(Impl->GenericParams, rep);
-      rep = archetype->getRepresentative();
-      equivClass = rep->getOrCreateEquivalenceClass();
-    }
+    auto equivClass = archetype->getOrCreateEquivalenceClass();
 
     assert(!equivClass->derivedSameTypeComponents.empty() &&
            "Didn't compute derived same-type components?");
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 3861ca5..567c036 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1503,9 +1503,8 @@
   public init?(exactly value: ${That}) {
     _value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(value._value)
 
-%   if srcBits >= SignificandBitCount:
-    guard let roundTrip = ${That}(exactly: self),
-      roundTrip == value else {
+%   if srcBits < SignificandBitCount:
+    if ${That}(self) != value {
       return nil
     }
 %   end
diff --git a/test/IRGen/associated_types.swift b/test/IRGen/associated_types.swift
index 7ddaf0e..64a07f4 100644
--- a/test/IRGen/associated_types.swift
+++ b/test/IRGen/associated_types.swift
@@ -71,7 +71,7 @@
   U.RuncerType.Runcee.accelerate()
 }
 
-// CHECK: define hidden swiftcc void @_T016associated_types16testFastRuncibleyx_q_1utAA0E0RzAA0dE0R_10RuncerTypeQy_AFRtzAF_6RunceeAA0F0PQZAF_AiA0dF0PRTzr0_lF(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T, %swift.type* %U, i8** %T.Runcible, i8** %U.FastRuncible) #0 {
+// CHECK: define hidden swiftcc void @_T016associated_types16testFastRuncibleyx_q_1utAA0E0RzAA0dE0R_10RuncerTypeQy_AFRtzr0_lF(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T, %swift.type* %U, i8** %T.Runcible, i8** %U.FastRuncible) #0 {
 //   1. Get the type metadata for U.RuncerType.Runcee.
 //     1a. Get the type metadata for U.RuncerType.
 //         Note that we actually look things up in T, which is going to prove unfortunate.
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index 790004b..f5c4685 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -658,12 +658,16 @@
             let uint = (number!) as? UInt
             expectEqual(UInt(exactly: interestingValue), uint)
 
-            let float = (number!) as? Float
-            let expectedFloat = Float(exactly: uint!)
-            testFloat(expectedFloat, float)
-
+            // these are disabled because of https://bugs.swift.org/browse/SR-4634
+            if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
+                let float = (number!) as? Float
+                let expectedFloat = Float(uint!)
+                testFloat(expectedFloat, float)
+            }
+            
+            
             let double = (number!) as? Double
-            let expectedDouble = Double(exactly: uint!)
+            let expectedDouble = Double(uint!)
             testDouble(expectedDouble, double)
         }
         let bridged = interestingValue as NSNumber
diff --git a/validation-test/compiler_crashers/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift b/validation-test/compiler_crashers_fixed/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift
similarity index 88%
rename from validation-test/compiler_crashers/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift
rename to validation-test/compiler_crashers_fixed/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift
index effc4cd..8b2df59 100644
--- a/validation-test/compiler_crashers/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift
+++ b/validation-test/compiler_crashers_fixed/28771-unreachable-executed-at-swift-include-swift-ast-cantypevisitor-h-41.swift
@@ -5,5 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 protocol A{typealias a{}typealias a=FlattenCollection}protocol b:A
diff --git a/validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
similarity index 89%
rename from validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
rename to validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
index b57ef5e..3902655 100644
--- a/validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
+++ b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
@@ -6,5 +6,5 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 class a:RangeReplaceableCollection}protocol P{{}typealias e:a{{}}typealias e:Collection
diff --git a/validation-test/compiler_crashers/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
similarity index 88%
rename from validation-test/compiler_crashers/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
rename to validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index 09986d1..14d2e3d 100644
--- a/validation-test/compiler_crashers/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -6,5 +6,5 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 protocol A:RangeReplaceableCollection&a:class a:A
diff --git a/validation-test/stdlib/FloatingPointConversion.swift.gyb b/validation-test/stdlib/FloatingPointConversion.swift.gyb
index 7489639..9882102 100644
--- a/validation-test/stdlib/FloatingPointConversion.swift.gyb
+++ b/validation-test/stdlib/FloatingPointConversion.swift.gyb
@@ -115,49 +115,74 @@
 
 %  end # for in all_floating_point_types (Other)
 
-#if arch(i386) || arch(arm)
-% int_types = all_integer_types(32)
-#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
-% int_types = all_integer_types(64)
-#else
-_UnimplementedError()
-#endif
+%{
 
-% for int_ty in int_types:
+float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion",
+"""
+% for int_ty in all_integer_types(word_bits):
 %  OtherInt = int_ty.stdlib_name
 %  OtherMin = int_ty.min
 %  OtherMax = int_ty.max
 %  (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed)
 
-FixedPointConversionTruncations.test("${OtherInt}to${Self}")
-  .forEach(in: [
-    (0, 0, 0),
-% if int_ty.bits > self_type.significand_bits + 1:
-%   limit = ~(~0 << (self_type.significand_bits + 1))
-%   over = ~(~0 << (self_type.significand_bits + 2))
-    (${limit}, ${limit}, ${limit}),
-    (${over}, ${over + 1}, nil),
-%   if int_ty.is_signed:
-    (-${limit}, -${limit}, -${limit}),
-    (-${over}, -${over + 1}, nil),
-%   end
-% else:
-    (${OtherInt}.min, ${OtherInt}.min, ${OtherInt}.min),
-    (${OtherInt}.max, ${OtherInt}.max, ${OtherInt}.max),
-% end
-  ] as [(${OtherInt}, ${OtherInt}, ${OtherInt}?)]) { value, roundedExpectation, exactExpectation in
-  let roundedResult = ${Self}(value)
-  expectEqual(roundedResult, ${Self}(roundedExpectation))
+%  for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]:
 
-  let exactResult = ${Self}(exactly: value)
-  if let expectation = exactExpectation {
-    expectEqual(exactResult!, ${Self}(expectation))
-  } else {
-    expectNil(exactResult)
-  }
+%    if testValue < OtherMin or testValue > OtherMax: 
+%          # Can't construct `other` value, do nothing and continue.
+
+%    elif testValue >= FloatMin and testValue <= FloatMax:
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") {
+  expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue})
 }
 
-%  end # for in int_types
+FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") {
+  expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue})
+}
+
+%    else:
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") {
+  let value: ${OtherInt} = ${testValue}
+  let result = ${Self}(value)
+  expectNotEqual(${OtherInt}(result), value)
+}
+
+FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") {
+  let value: ${OtherInt} = ${testValue}
+  let result = ${Self}(exactly: value)
+  expectEqual(result, ${OtherMin} as ${Self})
+  expectEqual(${OtherInt}(result!), value)
+}
+
+%    end
+
+%  end # testValue in testValues
+%  end # for in all_integer_types (Other)
+""")
+}%
+
+#if arch(i386) || arch(arm)
+
+  ${gyb.execute_template(
+      float_to_int_conversion_template,
+      word_bits=32,
+      **locals()
+      )}
+
+#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
+
+  ${gyb.execute_template(
+      float_to_int_conversion_template,
+      word_bits=64,
+      **locals()
+      )}
+
+#else
+
+_UnimplementedError()
+
+#endif
 
 %  if Self == 'Float80':
 #endif
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 8e99f2e..3e99a47 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -652,12 +652,16 @@
             let uint = (number!) as? UInt
             expectEqual(UInt(exactly: interestingValue), uint)
 
-            let float = (number!) as? Float
-            let expectedFloat = Float(exactly: uint!)
-            testFloat(expectedFloat, float)
-
+            // these are disabled because of https://bugs.swift.org/browse/SR-4634
+            if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
+                let float = (number!) as? Float
+                let expectedFloat = Float(uint!)
+                testFloat(expectedFloat, float)
+            }
+            
+            
             let double = (number!) as? Double
-            let expectedDouble = Double(exactly: uint!)
+            let expectedDouble = Double(uint!)
             testDouble(expectedDouble, double)
         }
         let bridged = interestingValue as NSNumber