Merge pull request #15038 from xedin/rdar-38203776-4.1

[4.1][AST] Disable comment printing while emitting diagnostics
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 6886f77..14568dd 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -3326,17 +3326,21 @@
   // Retrieve the requirement that a given typealias introduces when it
   // overrides an inherited associated type with the same name, as a string
   // suitable for use in a where clause.
-  auto getTypeAliasReq = [&](TypeAliasDecl *typealias, const char *start) {
+  auto getConcreteTypeReq = [&](TypeDecl *type, const char *start) {
     std::string result;
     {
       llvm::raw_string_ostream out(result);
       out << start;
-      out << typealias->getFullName() << " == ";
-      if (auto underlyingTypeRepr =
-            typealias->getUnderlyingTypeLoc().getTypeRepr())
-        underlyingTypeRepr->print(out);
-      else
-        typealias->getUnderlyingTypeLoc().getType().print(out);
+      out << type->getFullName() << " == ";
+      if (auto typealias = dyn_cast<TypeAliasDecl>(type)) {
+        if (auto underlyingTypeRepr =
+              typealias->getUnderlyingTypeLoc().getTypeRepr())
+          underlyingTypeRepr->print(out);
+        else
+          typealias->getUnderlyingTypeLoc().getType().print(out);
+      } else {
+        type->print(out);
+      }
     }
     return result;
   };
@@ -3466,51 +3470,68 @@
       inheritedTypeDecls.erase(knownInherited);
       continue;
     }
+  }
 
-    if (auto typealias = dyn_cast<TypeAliasDecl>(Member)) {
-      // Check whether we inherited any types with the same name.
-      auto knownInherited = inheritedTypeDecls.find(typealias->getFullName());
-      if (knownInherited == inheritedTypeDecls.end()) continue;
+  // Check all remaining inherited type declarations to determine if
+  // this protocol has a non-associated-type type with the same name.
+  inheritedTypeDecls.remove_if(
+    [&](const std::pair<DeclName, TinyPtrVector<TypeDecl *>> &inherited) {
+      auto name = inherited.first;
+      for (auto found : proto->lookupDirect(name)) {
+        // We only want concrete type declarations.
+        auto type = dyn_cast<TypeDecl>(found);
+        if (!type || isa<AssociatedTypeDecl>(type)) continue;
 
-      bool shouldWarnAboutRedeclaration =
-        source->kind == RequirementSource::RequirementSignatureSelf;
+        // ... from the same module as the protocol.
+        if (type->getModuleContext() != proto->getModuleContext()) continue;
 
-      for (auto inheritedType : knownInherited->second) {
-        // If we have inherited associated type...
-        if (auto inheritedAssocTypeDecl =
-              dyn_cast<AssociatedTypeDecl>(inheritedType)) {
-          // Infer a same-type requirement between the typealias' underlying
-          // type and the inherited associated type.
-          addInferredSameTypeReq(inheritedAssocTypeDecl, typealias);
-
-          // Warn that one should use where clauses for this.
-          if (shouldWarnAboutRedeclaration) {
-            auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol();
-            auto fixItWhere = getProtocolWhereLoc();
-            Diags.diagnose(typealias,
-                           diag::typealias_override_associated_type,
-                           typealias->getFullName(),
-                           inheritedFromProto->getDeclaredInterfaceType())
-              .fixItInsertAfter(fixItWhere.first,
-                                getTypeAliasReq(typealias, fixItWhere.second))
-              .fixItRemove(typealias->getSourceRange());
-            Diags.diagnose(inheritedAssocTypeDecl, diag::decl_declared_here,
-                           inheritedAssocTypeDecl->getFullName());
-
-            shouldWarnAboutRedeclaration = false;
-          }
-
-          continue;
+        // Or is constrained.
+        if (auto ext = dyn_cast<ExtensionDecl>(type->getDeclContext())) {
+          if (ext->isConstrainedExtension()) continue;
         }
 
-        // Two typealiases that should be the same.
-        addInferredSameTypeReq(inheritedType, typealias);
+        // We found something.
+        bool shouldWarnAboutRedeclaration =
+          source->kind == RequirementSource::RequirementSignatureSelf;
+
+        for (auto inheritedType : inherited.second) {
+          // If we have inherited associated type...
+          if (auto inheritedAssocTypeDecl =
+                dyn_cast<AssociatedTypeDecl>(inheritedType)) {
+            // Infer a same-type requirement between the typealias' underlying
+            // type and the inherited associated type.
+            addInferredSameTypeReq(inheritedAssocTypeDecl, type);
+
+            // Warn that one should use where clauses for this.
+            if (shouldWarnAboutRedeclaration) {
+              auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol();
+              auto fixItWhere = getProtocolWhereLoc();
+              Diags.diagnose(type,
+                             diag::typealias_override_associated_type,
+                             name,
+                             inheritedFromProto->getDeclaredInterfaceType())
+                .fixItInsertAfter(fixItWhere.first,
+                                  getConcreteTypeReq(type, fixItWhere.second))
+                .fixItRemove(type->getSourceRange());
+              Diags.diagnose(inheritedAssocTypeDecl, diag::decl_declared_here,
+                             inheritedAssocTypeDecl->getFullName());
+
+              shouldWarnAboutRedeclaration = false;
+            }
+
+            continue;
+          }
+
+          // Two typealiases that should be the same.
+          addInferredSameTypeReq(inheritedType, type);
+        }
+
+        // We can remove this entry.
+        return true;
       }
 
-      inheritedTypeDecls.erase(knownInherited);
-      continue;
-    }
-  }
+      return false;
+  });
 
   // Infer same-type requirements among inherited type declarations.
   for (auto &entry : inheritedTypeDecls) {
diff --git a/validation-test/compiler_crashers_2_fixed/0145-sr7097.swift b/validation-test/compiler_crashers_2_fixed/0145-sr7097.swift
new file mode 100644
index 0000000..4ae7282
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0145-sr7097.swift
@@ -0,0 +1,34 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
+// RUN: %target-swift-frontend -primary-file %s -emit-ir -o -
+
+protocol P1 { }
+
+protocol P2 {
+  associatedtype Assoc // expected-note{{'Assoc' declared here}}
+}
+
+// CHECK-LABEL: .P3@
+// CHECK-NEXT: Requirement signature: <Self where Self : P2, Self.Assoc == ConformsToP1>
+protocol P3 : P2 { }
+
+struct S0<M: P3> where M.Assoc: P1 { } // expected-warning{{redundant conformance constraint 'M.Assoc': 'P1'}}
+// expected-note@-1{{conformance constraint 'M.Assoc': 'P1' implied here}}
+
+struct ConformsToP1: P1 { }
+
+extension P3 {
+  typealias Assoc = ConformsToP1 // expected-warning{{typealias overriding associated type 'Assoc' from protocol 'P2' is better expressed as same-type constraint on the protocol}}
+}
+
+protocol P5 {
+}
+
+extension P5 {
+  // CHECK-LABEL: P5.testSR7097
+  // CHECK-NEXT: Generic signature: <Self, M where Self : P5, M : P3>
+  // CHECK-NEXT: <τ_0_0, τ_1_0 where τ_0_0 : P5, τ_1_0 : P3>
+  func testSR7097<M>(_: S0<M>.Type) {}
+}
+
+